组件构建--纸上谈兵02
组件是软件部署的单元,设计良好的组件可独立部署并可独立被开发。
1、组件聚合
--REP原则:复用/发布原则(不是很理解)
软件复用的最小粒度等同于其发布粒度。
解释:组件中的类与模块必须是彼此紧密相关的,一个组件不能由一组毫无关联的类和模块组成,它们应该有一个共同的主题和方向。一个组件中的类与模块还应该是可以同时发布的。
建议把组件组合的原则,为复用而组合。
--CCP原则:共同闭包原则
相当于组件版的SRP(单一职责原则:同时修改,有相同原因修改的函数放到一个类里)。同时修改,有相同的修改原因放到同一个组件里,否则不放在一起。
SRP是要把函数组装成类,而CCP是要把类组装成组件,虽然范围不同,但这两个原则本质上是一样的。
建议把组件组合的原则,为维护性而组合。
--CRP原则:共同复用原则:
相当于组件版的ISP(接口隔离原则:不要依赖带有不需要函数的类)。CRP是建议不要依赖带有不需要类的组件。
概括说就是不要依赖不需要的东西。
建议组合拆分的原则,为避免不必要的发布而拆分。(如果依赖了不需要的东西,那么每次发布,岂不是也要把这些不必要的东西也一起发布了。)
组件聚合张力图:
可以看到,REP,CCP是组合组合的,而CRP是建议拆分组件的,它们是相互矛盾的,那么如何在取舍呢?
如果只关注REP,CRP,会导致将来太多的组件变更(没有把相同修改原因的类放在一个组件里,而被分散开,那么将来这里分散开的类都要一起修改,影响多个组件)
如果只关注CCP,REP,也就是只关心组件的组合,不关注拆分,那么组件会起来越大,包含很多不必要的东西(修改组件中的某些类时并不影响这些类),每次更新,这些不必要的东西也要一起发布,从而引起过多不必要的发布。
所以应该在上图中根据项目阶段等因素选择一个最合适目录研发阶段的位置,也要根据时间等变化因素来调整。
例如在项目早期,由于研发速度比利用性重要,那么CCP会比REP原则重要。
一般来说,一个软件项目的重心会从右侧开始,先期牺牲复用性,随着项目逐渐成熟,其他项目会开始对其产生依赖,项目重心就要向左侧滑动。
2、组件耦合
--无依赖环原则
组件依赖关系图中不应该出现环。
A组件依赖B组件(依赖就是A组件中的类使用了B组件中的某些类),B组件依赖C组件,C组件又依赖于A组件
如:A组件中的Student类使用的课桌类Desk,造成了A对B的依赖。
消除依赖环:
只需要打破其中一组(如AB之间)
1、DIP:不再详细说了,用接口可以实现依赖反转
2、添加新组件,把都依赖的类放到这个组件里(上面的Desk类),放在D组件中
可见环已经被破坏了。
--稳定依赖原则
依赖关系必须要指向更稳定的方向。
一个组件的稳定性=出向依赖 / (出向依赖+入向依赖) ,值越小越稳定
出向依赖:也就是该组件依赖于其他组件,决定了本组件不得不发生变化(依赖的组件变化,本组件也必须跟随变量),是客观的
入向依赖:也就是依赖于本组件的组件,影响了本组件的变化,是主观的,当本组件想要发生变化时,依赖于本组件的这些组件会干预本组件发生变化,组件本组件的组件越多,说明干预变化的力量越多,也就越稳定,当没有组件依赖本组件时,也就是本组件想变化就发生变化,这样是不稳定的,要想让组件稳定,就让很多其他组件依赖于它(拖家带口是不容易逃跑的,没有顾虑不易控制)。
B组件稳定性=1/(3+1) = 1/4 C组件稳定性=0/(1+0) = 0, C组件稳定性更好,下面简单分析一下:
C没有依赖的组件,也就是说没有让C组件变更的原因,所以C很稳定;
B依赖于C,说明C改变也要引起B的改变,所以B较C来说不稳定。
E组件稳定性=1/(1+0) = 1, 最不稳定的情况(稳定性取值属于0到1区间),没有组件依赖它,也就是没有力量干预它的变更(B组件有三个依赖它的组件,也就是有三个干预它变更的力量),而且依赖于B组件,所以经常会变更,很不稳定。
!!并不是所有组件都要稳定,我们进行组件设计的目的就是决定让哪些组件稳定,哪些组件不稳定。
--稳定抽象原则:(上边那个叫稳定依赖原则)
一个组件的抽象化程度应该等于其稳定性。
稳定的组件应该是抽象的,不稳定的组件包含具体实现代码(以前说过,接口比具体实现是稳定的。)
抽象的可以用接口,也可以用抽象类。
稳定抽象原则:一个组件的抽象化程度应该等于其稳定性。
稳定依赖原则:依赖关系必须要指向更稳定的方向。
两个原则结合起来:依赖关系指向更抽象的方向,相当于组件层次上的DIP原则。
参考:《Clean Architecture》
以上为书中内容添加个人理解,如有错误,欢迎指正。