0.2.4 原则#1的代价
世上没有免费的午餐。使用原则#1是有代价的。
为了从代码和数据之间的分离中获益,我们必须付出的代价是:
- 对什么代码访问什么数据没有控制
- 没有包装
- 我们的系统是由更多的实体组成的
代价#1:无法控制什么代码访问什么数据
当代码和数据混合在一起时,人们可以很容易地理解哪些是访问某种数据的代码片断。
例如,在OO中,数据被封装在一个对象中。它保证了数据只能被对象的方法所访问。
在DO中,数据是自成一体的。如果你愿意,它是透明的。因此,它可以被任何一段代码所访问。
当我们想重构数据的形状时,我们需要非常小心,确保我们知道代码中所有访问数据的地方。
如果不应用执行数据不变性的第3条原则,数据可以被任何一段代码访问的事实将是非常不安全的,因为很难保证我们数据的有效性。
TIP 数据安全由另一个原则(原则#3)来保证,该原则执行数据的不变性。
代价#2:无包装
混合代码和数据的好处之一是,当你有一个对象在手时,它是一个包,它同时包含了代码(通过方法)和数据(通过成员)。
因此,作为一个开发者,很容易发现有哪些操作数据的方法:你看一下类的方法。
在DO中,操作数据的代码可能无处不在。例如,createAuthorData可能在一个文件中,fullName在另一个文件中。这使得开发人员很难发现fullName函数是可用的。在某些情况下,这可能会导致时间的浪费和不必要的代码重复。
我们将在整本书中探索各种方法来缓解这一缺点
代价#3:我们的系统是由更多的实体组成的
让我们来做简单的算术。想象一下,一个由N个结合了代码和数据的类组成的系统。当你把这个系统分成代码实体和数据实体时,你会得到一个由2N个实体组成的系统。
这种计算并不准确,因为通常当你把代码和数据分开时,类的层次结构往往会变得更简单,因为我们需要更少的类继承和组合。因此,结果系统中的类的数量可能会在N和2N之间。
一方面,当我们坚持原则#1时,我们系统的实体就比较简单了。
另一方面,我们有更多的实体。
这一代价被原则#2所缓解,该原则指导我们用通用数据结构表示我们的数据
TIP 在坚持原则#1的时候,我们的系统是由更简单的实体组成的,但我们有更多的实体。
0.2.5 总结
DO指导我们将代码与数据分开。
在OO语言中,我们将代码聚集在静态类中,将数据聚集在没有方法的类中。
在FP语言中,我们避免在函数的词法范围内隐藏数据。
将代码与数据分离是有代价的:它减少了我们对哪些代码访问数据的控制,并可能导致我们的系统由更多的实体组成。
但是付出这样的代价是值得的,因为当我们坚持这一原则时,我们的代码可以在不同的环境中直接重复使用,并在隔离的情况下测试。此外,一个由代码和数据的独立实体组成的系统往往更容易理解。
在数据与代码分离之后,就出现了如何表示数据的问题。这就是原则#2的主题
侧边栏
DO原则#1:将代码与数据分开
原则
将代码与数据分开,使代码存在于函数中其行为并不依赖于以某种方式封装在函数上下文中的数据。
好处
- 代码可以在不同的环境中重复使用
- 代码可以单独测试
- 系统趋于没有那么复杂
代价
- 无法控制什么代码访问什么数据
- 没有包装
- 我们的系统是由更多的实体组成的