高质量的类 —— 《clean code》读后感
类应该短小,从这个意义上来说,类和函数有很多相似点,但衡量函数的“小”可以通过代码行数,而衡量类的大小是通过“权责”。
类的名称应当描述其权责,实际上,命名正是帮助判断类的长度的第一个手段,如果无法为某个类命以精确的名称,这个类大概就太长了。如果类的命名越含混,不够精确,该类越有可能拥有过多权责。
我们也应该能够用大概25个单词简要描述一个类,且不用“若”、“与”、“或者”、“但”等词。记住,类应该简单,权责单一。
类应该遵循单一权限原则(SRP)。但如果遵循此原则,就会产生数量巨大的类。许多开发者害怕数量巨大的短小单一目的的类会导致难以一目了然抓住全局。他们认为,要搞清楚一件较大工作如何完成,就得在类与类之间找来找去。然而,有大量短小类的系统并不比有少量庞大类的系统拥有更多移动部件,其数量大致相等。问题是:你是想把工具归置到有许多抽屉、每个抽屉中装有定义和标记良好的组件的工具箱中呢,还是想要少数几个能随便把所有东西扔进去的抽屉?
再强调一下:系统应该由许多短小的类而不是少量巨大的类组成。每个小类封装一个权责,只有一个修改的原因,并与少数其他类一起协同达成期望的系统行为。
管理大量小类的最有效办法就是给类分抽象层次。而在修改的时候,要自顶向下阅读,逻辑渐渐展现开来,不会在抽象层级较高的层面就陷入实现的细节中。
好的类应该是高内聚的。通常而言,方法操作的变量越多,就越黏取到类上。如果一个类中的每个变量都被每个方法所使用,则该类具有最大的内聚性。一般来说,创建这种极大化内聚类是既不可取也不可能的;另一方面,我们希望内聚性保持在较高位置。内聚性高,意味着类中的方法和变量互相依赖、互相结合成一个逻辑整体。
前面我们说过,函数应该保持短小,参数较少。我们应尽量将大函数拆分成小函数,将多参数减小成少参数。在拆分大函数的时候,如果想减少参数的数量,我们可以将参数提升为类的属性,而不是方法的参数。如果一来,在拆分大函数为小函数的时候,会扩大类属性的数量,而这个属性可能只被极少数的方法所调用,从而降低了类的内聚性。出现这种情况时,往往意味着至少有一个类要从大类中挣扎出来。你应当尝试将这些变量和方法拆分到两个或多个类中,让新的类更为内聚。
没错,保持内聚性就会得到许多短小的类。当类丧失了内聚性,就拆分它!所以,将函数拆为许多小函数,往旆也是将类拆分为小类的时机。程序会更加有组织,也会拥有更为透明的结构。
高质量的类,应满足以下几点:
1) 单一权责(SRP)。 上面讲了很多了,如何做到这一点。
2) 开放-闭合原则(OCP)。类应当对扩展开放,对修改封闭。(关于这一点,推荐看一下《大话设计模式》,这方面讲得非常透彻)
3) 依赖倒置原则(DIP)。类应该尽量避免直接对其它类(或实例)进行调用,这会让类了解过多其它类实现的细节,让类之间产生强耦合。类与类之间的关联应该通过接口实现,具体来说,如果A类需要调用B类的方法,应该将B类通过参数传给A类,赋值给A类的一个属性。B类通过这种方式让A类调用其方法,对于A类来说,它并不依赖B类,只是调用自己的属性的方法。至于属性从哪儿来,除了赋值那一步,其它任何地方都不用关心。所以如果要做修改,也只用修改自己的属性,可以很轻易让自己的属性指向别的类,易于修改。类和类之间的耦合,仅在于接口处。