重构读书笔记六——封装

重构 Dec 30, 2020

概述

分解模块时候最重要的标准,可能就是识别出应该对外界隐藏的小秘密。

6.1 封装变量

描述

以数据类取代变量

动机

很多语言都有map或者字典这种数据结构。很多程序中使用这种数据结构来传递数据。这种数据结构里面的传递的数据对于不了解业务的来说非常模糊,没办法体现业务。对于重构来说也很难去重构,因为没办法区分使用的范围。用数据类(在java里面可以叫数据bean)来表示能更好的来明确数据的传递,也能限制数据使用的范围。

6.2 封装集合

描述

把对集合的操作封装起来,对外暴露一个只读的代理。把对集合的修改封装到一个函数中。
[me]:这点对java来说比较容易实现,其他语言应该也都可以。

动机

这和上一条的理由类似,主要是封装起来方便数据的追踪和限制访问。

6.3 用对象取代基本类型

描述

用一个类来表示基本类型。这个类除了体现基本类型本来的功能,可以添加常用的操作(格式化,相同的比较),限制对数据的修改,另外还可以呈现和追踪业务逻辑。

动机

电话号码,钱,温度。或许我们一开始用基本数据类型来表示(字符串或者整形,浮点数)。但随着开发的进行,我们发现用基本数据类型也不再那么见简单了。我们需要格式化,添加前缀,不同情况的转换等等不同的特殊行为。这时候我们应该使用一个类来取代基本类型

6.4 用查询取代临时变量

描述

作者提倡把临时变量的计算变成一个函数,然后需要的时候直接用函数计算获取值。
[me]:我觉得不是说每一个临时变量的计算都要这么做。对于重复出现或者说在业务中一定会出现的临时变量提倡用这种方式。比如说:计算税率的时候中间要计算增值税,扣税部分和非扣税部分等等,这种函数就有了意义。

动机

临时变量的一个作用是保存某段代码的返回值,以便在函数的后面部分使用。临时变量允许引用之前的值,既能解释它的含义,还能避免对代码进行重复计算。

6.5 提炼类

描述

当一个类变得越来越大的时候,我们可以考虑把这个类里面的部分抽离出来变成一个新类
[me]:在项目里面见过一个类有好几千甚至上完行的代码,或者这样类的确是代表了一个业务领域,但是在这个大的领域下面一定还有很多小的领域。或者从不同的角度和功能来说,可以进行更进一步的划分,而不是把代码都写进一个类里面。

动机

一个类应该是一个清晰的抽象,只处理一些明确的责任。但在实际工作中,类会不断成长扩展。你需要考虑把哪些部分可以分离出去?如果某些数据总是和某些函数一起出现,某些数据经常同时变化甚至彼此依赖,这就表示应该将他们分离出去了。

6.6 隐藏委托关系

描述

把中间的委托类,委托接口隐藏起来。不要让调用方感知到,当我们修改委托类,修改委托的协议时候,对客户端来说就是透明的。

动机

一个好的模块化设计,封装即使不是其最关键特征,也是最关键特征之一。封装意味着每个模块都应该尽可能少了解系统的其他部分。如此以来,一旦发生变化,需要了解变化的模块就会比较少——这会使变化比较容易进行。
除了隐藏数据和行为,对于中间过程(委托关系),我们也可以进行隐藏。比如:如果客户端通过接口获取到一个字段,然后再通过这个字段去获取另一个对象(别惊讶好多微服务都这么干)。第一个接口对于客户端就是一个委托调用,我们可以隐藏这个过程,将调用转移到第二个接口或者说提供一个统一的代理接口来整合接口一和接口二。这样即使将来接口一发生变化也不会影响到客户端。

6.7 移除中间人

描述

如果对于一个接口来说一个代理类能做的太少,那么就没有存在的必要。

动机

隐藏委托关系的例子中,我们可以通过让接口二整合接口一的字段,把接口一去掉。这就是一种移除中间人的方式。或许某些时候代理有存在的必要,但随着时间的推移代理的作用越来越小,那么就没有存在的必要。把代理去掉,直接调用对应的接口吧。

6.8  逻辑替换

描述

对我来说,代码并不是能用就行了。当我们发现代码可以用更简洁,更高效的方式实现的逻辑的时候,不要犹豫去重写吧。举个例子:java有了lambda表达式后很多逻辑都可以重构,用lambda表达式逻辑更简洁。支持option的语言,就可以替换无尽的if的判断了。

动机

对代码质量有一定的追求。

总结

这一章把封装的逻辑写完了,下一章总结如何抽离代码。