[长沙好代码系列]代码优雅之---代码阅读性

原创
2013/11/15 02:45
阅读数 379

代码的阅读性并非我们平常说的代码可读性

代码阅读性 是我提出来的概念, 独创但是没有版权。特意和代码可读性区别开来;更加强调业务概念而不是技术名词。 现给出一个极端的标准:

如果一行代码, 不能5秒钟内看出它的功能,我们可以说这段代码的阅读性不佳。

下面我们来看一段例子。

以下这段代码,是我的依赖注入框架中的一小段代码。

private readonly IDictionary<Type, resolver> item_resolvers;
public IEnumerable<Interface> get_all<Interface>()
{
    var type = typeof (Interface);
    foreach (var pair in item_resolvers) 
    {
        if (type.IsAssignableFrom(pair.Key))
        yield return (Interface) pair.Value.resolve();
    }
}

首先,介绍一下背景:这个方法get_all<Interface>()是从依赖注入容器中得到所有实现了指定接口<Interface>的对象实例。忽略细节,这个方法的核心是循环容器中每一个的类解析器,比较该类是否实现或继承了指定的接口。

第6行if (type.IsAssignableFrom( pair.Key ))判断实现或继承用到了C#的一个方法,IsAssignableFrom()这里是微软对该方法的定义。摘自: http://msdn.microsoft.com/ZH-cn/library/system.type.isassignablefrom.aspx

public virtual bool IsAssignableFrom(Type c)

如果 c 和当前 Type 表示同一类型,当前 Type 在 c 的继承层次结构中,当前 Type 是 c 实现的接口,c 是泛型类型参数且当前 Type 表示 c 的约束之一,或 c 表示值类型且当前 Type 表示 Nullable(Visual Basic 中的 Nullable(Of c)),则为 true。 如果不满足上述任何一个条件或者 c 为 null,则为 false。

IsTypeAssinableForm(Type c) 中c和返回的Type, 那个是子类,哪个是父类

即使看完了帮助文字,有谁知道,这个方法两边的类型,哪个是子类,哪个是父类?

对那些知道的人,我想说:恭喜你,你已经不是正常人了。我至今仍然没记住,到底哪里个是哪个。

这个方法名是一个典型的实现命名法,我猜想,它的内部的实现机制,可能就是判断一个类型是赋值过另一个类型。而作为该功能用户的我,如前面的背景所述,想知道,是谁继承了谁。因此:

其实我只需要这样的一个方法 type.is_inherited_from(Type c)

首先,脱离开刚才的产品代码,我们对我们创造的新方法做一个剥离,剥离到哪去,到测试中去。

public class TypeExtensionsSpecs
{
    class base_class { }
    class child_class : base_class { }

    private It the_class_is_not_inheried_from_itself =
        () => typeof(base_class).is_inherited_from(typeof(base_class)).ShouldBeFalse();

    private It the_base_class_is_not_inheried_from_its_child_class =
        () => typeof(base_class).is_inherited_from(typeof(child_class)).ShouldBeFalse();

    private It the_child_class_is_not_inheried_from_its_base_class =
        () => typeof(child_class).is_inherited_from(typeof(base_class)).ShouldBeTrue();
}

请先忽略那些与测试框架相关的龙套代码,如It甚至Lambda表达式, 如果有时间,后面的主题可以专门讲讲行为测试框架MSpec。这里我定义了两个类,一个子类。很明显,我的测试就是预期,子类是基类的子类,嗯有点绕口,但无论是我口头的描述,还是非常近似的测试代码描述,是很清楚明白的,是不是不到5秒能完全看懂?

我们来看实现

public static bool is_inherited_from(this Type type, Type base_type)
{
    return !(type == base_type) && base_type.IsAssignableFrom(type);
}

即算做了n遍,到这个实现代码我几乎仍然是拼凑以期让测试通过,因为我实在是弄出清楚IsAssignableFrom的方向性。只有测试让我更清楚些。

技术上,没有别的,主要用到了.Net的新特性 Extension

说新其实也不新了。至少我都用了3、5年了。我想这个名称应该来源于所谓的开闭原则,对修改关闭,对扩展开放,这就是一个扩展功能,还是名副其实。

修正之后的产品代码

作为完结我们看看应用新方法之后的原代码。是不是好懂很多,也就减少了bug的机会,你想写反都难!

private readonly IDictionary<Type, resolver> item_resolvers;
public IEnumerable<Interface> get_all<Interface>()
{
    var type = typeof (Interface);
    foreach (var pair in item_resolvers) 
    {
        /* 新代码                                  */
        if (pair.Key.is_inherited_from(type))
        yield return (Interface) pair.Value.resolve();
    }
}

代码阅读性之路仍很漫长

刚好,说到这里,在阅读性上,我们这一段代码还可走的更远,如用Linq来替换循环和过滤的功能,等等。不管,我们现在有多不完美,但是至少我们是朝着正确的方向!

(本文版权属于© 2012 - 2013 予沁安 | 转载请注明作者和 出处
展开阅读全文
打赏
0
9 收藏
分享
加载中
予沁安博主

引用来自“Kenven”的评论

这部就是可读性?要不楼主理解的可读性是什么?

IsAssignableFrom 是可读性,is_inherited_from是阅读性。
2013/11/16 00:00
回复
举报
这部就是可读性?要不楼主理解的可读性是什么?
2013/11/15 09:04
回复
举报
更多评论
打赏
2 评论
9 收藏
0
分享
返回顶部
顶部