你好,我是七牛云许式伟。
总结来说,开闭原则包含以下两层含义:
第一,模块的业务要稳定。模块的业务遵循 “只读” 设计,如果需要变化不如把它归档,放弃掉。这种模块业务只读的思想,是架构治理的基础哲学。我平常和小伙伴们探讨模块边界的时候,经常会说这样一句话:
这实际上是开闭原则的业务范畴 “只读” 的架构治理思想的另一种表述方式。
第二,模块业务的变化点,简单一点的,通过回调函数或者接口开放出去,交给其他的业务模块。复杂一点的,通过引入插件机制把系统分解为 “最小化的核心系统 + 多个彼此正交的周边系统”。事实上回调函数或者接口本质上就是一种事件监听机制,所以它是插件机制的特例。
上一讲我们介绍了接口设计。到此为止,我们的架构思维篇也已经基本接近尾声。可能有人会越来越奇怪,为什么我还是没有去聊那些大家耳熟能详的架构设计原则?
实际上,并不是这些架构设计原则不好,它们之中不乏精彩绝伦、振聋发聩的总结。比如:
接口隔离原则(Interface Segregation Principle,ISP):一个模块与另一个模块之间的依赖性,应该依赖于尽可能小的接口。
依赖倒置原则(Dependence Inversion Principle,DIP):高层模块不应该依赖于低层模块,它们应该依赖于抽象接口。
无环依赖原则(Acyclic Dependencies Principle,ADP):不要让两个模块之间出现循环依赖。怎么解除循环依赖?见上一条。
组合 / 聚合复用原则(Composition/Aggregation Reuse Principle,CARP):当要扩展功能时,优先考虑使用组合,而不是继承。
高内聚与低耦合(High Cohesion and Low Coupling,HCLC):模块内部需要做到内聚度高,模块之间需要做到耦合度低。这是判断一个模块是在做一个业务还是多个业务的依据。如果是在做同一个业务,那么它所有的代码都是内聚的,相互有较强的依赖。
惯例优于配置(Convention over Configuration,COC):灵活性会增加复杂性,所以除非这个灵活性是必须的,否则应尽量让惯例来减少配置,这样才能提高开发效率。如有可能,尽量做到 “零配置”。
命令查询分离(Command Query Separation,CQS):读写操作要分离。在定义接口方法时,要区分哪些是命令(写操作),哪些是查询(读操作),要将它们分离,而不要揉到一起。
关注点分离(Separation of Concerns,SOC):将一个复杂的问题分离为多个简单的问题,然后逐个解决这些简单的问题,那么这个复杂的问题就解决了。当然这条说了等于没说,难在如何进行分离,最终还是归结到对业务的理解上。