面向对象设计原则SOLID最早是由Bob大叔在其2000年的论文<Design Principles and Design Patterns>中提出的。SOLID的具体指的是下面五个原则:单一职责原则、开闭原则、里氏替换原则、接口分离原则、依赖倒置原则。它们主要是对类的设计原则。为什么SOLID被提出呢?
SRP | The Single Responsibility Principle | A class should have one, and only one, reason to change. |
OCP | The Open Closed Principle | You should be able to extend a classes behavior, without modifying it. |
LSP | The Liskov Substitution Principle | Derived classes must be substitutable for their base classes. |
ISP | The Interface Segregation Principle | Make fine grained interfaces that are client specific. |
DIP | The Dependency Inversion Principle | Depend on abstractions, not on concretions. |
要解决的问题
面向对象的编程提出并被广泛应用很长一段时间后,软件开发还是存在一些典型的问题。例如一个添加一个新功能或者修改一个bug,会发现代码里很多地方需要改动,并且要想遵循以前的设计思路需要的改动更多更大,所以开发人员往往会选择一些打补丁的方式。这样下来,系统的代码越来越晦涩难懂,经常在一个地方修改bug,会引起另一个看起来毫不相关的地方出问题。慢慢的这个系统的设计就完全烂掉了,能重用的部分也抽不出来。
然而理想的情况应该是,随着需求的变化演进,开发人员只要添加新代码(而不需要碰老代码)来实现这些需求;改bug也只需在一个特定地方修改而无需担心其他方法受影响。
这理想与现实间的差距,就是面向对象设计原则要解决的问题。
解决的思路
开闭原则像是目标,我们要达到扩展功能的同时不需要改动已有代码;而依赖倒置原则和单一职责原则是手段,要通过依赖于抽象接口而非具体实现的方式去扩展功能,通过单一职责去减少类之间的复杂依赖关系。里氏替换原则可以确保依赖倒置里的抽象接口确实可以被不同的具体类相互替换,从而达到扩展功能的目的。而接口分离原则也是为更好管理类直接的依赖,使得依赖关系更简洁清晰。这里的两个关键是对接口/类边界的定义和对抽象依赖的管理。边界明确了,依赖自然也会清晰。然后再通过添加新的层来解耦新需求带来的复杂依赖,这样保持原始设计的稳定和演化。
引发的思考
现在的微服务系统设计和类的设计有很多类似之处,无论是面对的问题还是解决的思路。确保每个微服务的职责单一、边界清晰,和其他微服务间以契约/接口的方式通信,引入“额外的”微服务来解耦过于复杂的服务间依赖,这样可以保证微服务系统清晰、易扩展,多活几年而不腐化。
第二周课堂内容总结-思维导图
参考文献:
1. "Design Principles and Design Patterns", Robert C. Martin, 2000. https://fi.ort.edu.uy/innovaportal/file/2032/1/design_principles.pdf
2. "Principles of OOD", Robert C. Martin. http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod