《架构整洁之道》之组件聚合
一、复用/发布原则
软件复用的最小粒度应等同于其发布的最小粒度。
从软件设计与架构设计的角度来看,复用/发布原则就是指组件中的类与模块必须是彼此紧密相关的。也就是说,一个组件不能由一组毫无关联的类和模块组成,它们之间应该有一个共同的主题或者大方向。
从另一个角度来看,这个原则就没有那么简单。因为根据该原则,一个组件中包含的类与模块还应该是可以同时发布的。这意味着它们共享相同的版本号与版本跟踪,并且包含在相同的发行文档中,这些都应该同时对该组件的作者和用户有意义。
二、共同闭包原则
我们应该将那些会同时修改,并且为相同目的而修改的类放到同一个组件中,而将不会同时修改,并且不会为了相同目的而修改的那些类放到不同的组件中。
共同闭包原则的主要作用:
提示我们要将所有可能会被一起修改的类集中在一处。也就是说,如果两个类紧密相关,不管是源代码层面还是抽象理念层面,永远都会一起被修改,那么它们就应该被归属为同一个组件。通过遵守这个原则,我们就可以有效地降低因软件发布、验证及部署所带来的工作压力。
共同闭包原则和开闭原则也是紧密相关的。共同闭包原则讨论的就是开闭原则中所指的”闭包”。开闭原则认为一个类应该便于扩展,而抗拒修改。由于100%的闭包是不可能的,所以我们只能战略性地选择闭包范围。在设计类的时候,我们需求根据历史经验和预测能力,尽可能地将需要被一同变更的那些点聚合在一起。
对于共同闭包原则,我们还可以在此基础上做进一步的延伸,即可以将某一类变更所涉及的所有类尽量聚合在一处。这样当此类变更出现时,我们就可以最大限度地做到使该类变更只影响到有限的相关组件。
共同闭包原则实际上是单一职责原则的组件版。在单一职责原则的指导下,我们将会把变更原因不同的函数放入不同的类中。而共同闭包原则指导我们应该将变更原因不同的类放入不同的组件中。简而言之,这两个原则都可以用下面一句话来概括:
将由于相同原因而修改,并且需要同时修改的东西放在一起。将由于不同原因而修改,并且不同时修改的东西分开。
三、共同复用原则
不要强迫一个组件的用户依赖他们不需要的东西。
共同复用原则是另外一个帮助我们决策类和模块归属于哪一个组件的原则。该原则建议我们将经常共同复用的类和模块放在同一个组件中。
通常情况下,类很少会被单独复用。更常见的情况是多个类同时作为某个可复用的抽象定义被共同复用。CRP原则指导我们将这些类放在同一个组件中,而在这样的组件中,我们应该预见到会存在许多相互依赖的类。
共同复用原则的作用不仅是告诉我们应该将哪些类放在一起,更重要的是要告诉我们应该将哪些类分开。因为每当一个组件引用另一个组件时,就等于增加了一条依赖关系。虽然这个引用关系仅涉及被引用组件中的一个类,但它所带来的依赖关系丝毫没有减弱。也就是说,引用组件已然依赖于被引用组件了。
由于这种依赖关系的存在,每当被引用组件发生变更时,引用它的组件一般也需要做出相应的变更。即使它们不需要进行代码级的变更,一般也免不了需要被重新编译、验证和部署。哪怕引用组件根本不关心被引用组件中的变更,也要如此。
因此,当我们决定要依赖某个组件时,最好是实际需要依赖该组件中的每个类。换句话说,我们希望组件中的所有类是不能拆分的,即不应该出现别人只需要依赖它的某几个类而不需要其他类的情况。否则,我们后续就会浪费不少时间与精力来做不必要的组件部署。
因此在共同复用原则中,关于哪些类不应该被放在一起的建议是其更为重要的内容。简而言之,共同复用原则实际上是指导我们:不要紧密相连的类不应该被放在同一个组件里。
共同复用原则实际上是接口隔离原则的一个普适版。接口隔离原则建议我们不要依赖带有不需要的函数的类,而共同复用原则则是建议我们不要依赖带有不需要的类的组件。
上述两条建议实际上都可以用下面一句话来概括:
不要依赖不需要用到的东西。