背景介绍
这是我的《架构整洁之道》系列的第十二篇,我们将一起学习组件聚合~
《架构整洁之道》系列:
组件聚合
三个与构建组件相关的基本原则:
- REP: 复用/发布等同原则
- CCP: 共同闭包原则
- CRP: 共同复用原则
复用 / 发布等同原则
软件复用的最小粒度应等同于其发布的最小粒度
模块管理工具得到了长足的发展,例如 Maven、 Leiningen、 RVM 等。而这些工具日益重要的原因是出现了大量可复用的组件和组件库。
如果想要复用某个软件组件的话,一般就必须要求该组件的开发由某种发布流程来驱动,并且有明确的发布版本号。如果没有设定版本号,我们就没有办法保证所有被复用的组件之间能够彼此兼容。另外更重要的一点是,软件开发者必须要能够知道这些组件的发布时间,以及每次发布带来了哪些变更。只有这样,软件工程师才能在收到相关组件新版本发布的通知之后,依据该发布所变更的内容来决定是继续使用旧版本还是做些相应的升级。
因此,组件的发布过程还必须要能够产生适当的通知和发布文档,以便让它的用户根据这些信息做出有效的升级决策。
从软件设计和架构设计的角度来看,REP 原则就是指组件中的类与模块必须是彼此紧密相关的。也就是说,一个组件不能由一组毫无关联的类和模块组成,它们之间应该有一个共同的主题或者大方向。
从另一个视角来看,一个组件中包含的类与模块还应该是可以同时发布的。这意味着它们共享相同的版本号与版本跟踪,并且包含在相同的发行文档中,这些都应该同时对该组件的作者和用户有意义。
共同闭包原则
我们应该将那些会同时修改,并且为相同目的而修改的类放到同一个组件中,而将不会同时修改,并且不会为了相同目的而修改的那些类放到不同的组件中。
也就是说:如果两个类紧密相关,不管是源代码层面还是抽象理念层面,永远都会一起被修改,那么它们就应该被归属为同一个组件。通过遵守这个原则,我们就可以有效地降低因软件发布、验证及部署所带来的工作压力。
我们还可以在此基础上做进一步的延伸:即可以将某一类变更所涉及的所有类尽量聚合在一处。这样当此类变更出现时,我们就可以最大限度地做到使该类变更只影响到有限的相关组件。
将由于相同原因而修改,并且需要同时修改的东西放在一起。将由于不同原因而修改,并且不同时修改的东西分开。
共同复用原则
不要强迫一个组件的用户依赖他们不需要的东西。
该原则建议我们将经常共同复用的类和模块放在同一个组件中。因此,当我们决定要依赖某个组件时 ,最好是实际需要依赖该组件中的每个类。换句话说,我们希望组件中的所有类是不能拆分的,即不应该出现别人只需要依赖它的某几个类而不需要其他类的情况。
在共同复用原则中,关于哪些类不应该被放在一起的建议是其更为重要的内容。简而言之,共同复用原则实际上是在指导我们:不是紧密相连的类不应该被放在同一个组件里。
言简意赅的说:不要依赖不需要用到的东西
组件聚合张力图
上述三个原则之间彼此存在着竞争关系。REP 和 CCP 原则是勤合性原则,它们会让组件变得更大,而 CRP 原则是排除性原则,它会尽量让组件变小。
软件架构师的任务就是要在这三个原则中间进行取舍。
下图是一张组件聚合三大原则的张力图,图的边线所描述的是忽视对应原则的后果。
只关注 REP 和 CRP 的软件架构师会发现,即使是简单的变更也会同时影响到许多组件。相反,如果软件架构师过于关注 CCP 和 REP,则会导致很多不必要的发布。
优秀的软件架构师应该能在上述三角张力区域中定位一个最适合目前研发团队状态的位置,同时也会根据时间不停调整。
一般来说,一个软件项目的重心会从该三角区域的右侧开始,先期主要牺牲的是复用性。然后,随着项目逐渐成熟,其他项目会逐渐开始对其产生依赖,项目重心就会逐渐向该三角区域的左侧滑动。
结束语
在决定将哪些类归为同一个组件时,必须要考虑到研发性与复用性之间的矛盾,并根据应用程序的需要来平衡这两个矛盾,这是一件很不容易的事。而且,这种平衡本身也在不断变化。也就是说,当下适用的分割方式可能明年就不再适用了。
所以,组件的构成安排应随着项目重心的不同,以及研发性与复用性的不同而不断演化。
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨
少年向来不识天高地厚
放眼处皆自负才高八斗
虽是自命风流
倒也坦诚无忧
我爱这样的少年
谦和而狂妄
骄傲又坦然☀️
✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨