Litong's Blog

Work to become, not to acquire.

第7章 封装

分解模块时最重要的标准是,识别出那些模块应该对外界隐藏的细节。

类是为隐藏信息而生的。

除了类的内部细节,使用隐藏委托关系来隐藏类之间的关联关系通常也很有帮助(反向注入)。

类与模块已然是施行封装的最大实体了,但小一点的函数对于封装实现细节也有所裨益。

封装记录

以数据类取代记录(Replace Record with Data Class)

记录型结构能直观地组织起存在关联的数据,可以将数据作为有意义的单元传递,而不仅是一堆数据的拼凑。

封装集合

对程序中的可变数据进行封装,这样很容易看清楚数据被修改的地点和修改方式。

封装集合时如果让取值函数返回集合本身,则将集合的修改也扩散到了所有使用它的地方。应该通过”添加“和”移除“方法,来让集合的修改必须通过类。

依赖于别人的好习惯是不明智的。不要让集合的取值函数返回原始集合,避免客户端的意外修改。

以对象取代基本类型

将数据包装成类,后续添加的业务逻辑则可以封装进去。数据被使用的越多,包装成类对代码库的影响就更深远。

以查询取代临时变量

临时变量允许我们使用之前的值,还能解释它的含义,避免重复计算,但值得更进一步,抽取成查询函数。

将变量的计算逻辑放到函数中,也有助于在函数之间设立清晰的边界,这可以帮助我们发现并避免难缠的依赖及副作用。

提炼类

一个类应该只是一个清晰的抽象,只处理一些明确的责任。但类会不断随着业务逻辑扩展,当责任不断增加,此时就需要考虑将类分离出去。

如果某些特性只影响类的部分特性,或者某些特性需要以另一种方式子类化,这就意味着你需要分解原来的类。

内联类

如果一个类不在承担足够责任,不再有单独存在的理由,通常可以将其内联到另一个类中。

隐藏委托关系

封装是一个好的模块化设计的最关键特征之一。封装意味着每个模块都应该尽可能少地了解系统的其他部分。

有更多值得封装的东西,比如客户端调用的服务,可以将委托关系隐藏起来,及时将来委托关系发生变化,也只会影响服务对象,而不会直接波及所有客户端。

移除中间人

移除中间人是隐藏委托关系的反向重构,当需要委托的特性越来越多时,更多的转发函数会使人烦躁。这个时候可以通过移除中间人,让客户端直接调用服务。

重构的意义就在于:你永远不必说对不起——只需要把出问题的地方修补好就行了。

替换算法

用简单清晰的方式取代复杂的方式。

替换一个巨大且复杂的算法是非常困难的,需要先将它分解为简单的小型函数。