众所周知,设计原则是设计模式的基石。当遵循设计原则的时候,写出的代码就会变得非常灵活,并且可以应对变化,也更加容易维护。当然,也不是那么绝对。下面首先会简要介绍一些基本的设计原则,然后再介绍Robert C. Martin的S.O.L.I.D原则。
1 设计原则简述
KISS原则(Keep It Simple Stupid)
软件开发中常常遇到的问题就是:把一个问题过度的复杂化。KISS原则的目的就是提倡在设计和编码中,尽量保持代码的简约,避免不必要的复杂。简约不等于简单。
DRY原则(Don’t Repeat Yourself)
DRY原则的目的就是:抽取系统中的公共部分,并把它放置在一个地方以避免重复。这个原则不只是适用于代码中,而且也可以用于功能和业务逻辑上,确保不重复。这就要求对系统的职能有良好的分割,每个功能之间有着清晰的界限,用例之间不存在交叉。
Tell,Don’tAsk
这个原则是与封装有关的,要求对代码进行合理的封装,并把它们放到正确的类中。同时这个原则也指出:必须明确告诉对象:我们想要它们去执行什么样的操作,而不是首先询问对象的状态,然后我们自己决定去执行什么操作。
YAGNI原则(You Ain’tGonna Need It)
YAGNI原则指出:系统中只包含所必须的功能,不要包含你认为将来可能会用到的功能或者特性,防止过度设计。这个原则在TDD中体现得比较完全。在TDD中,首先写出代表系统必须功能的测试用例,然后再实现系统的功能代码,然后进行测试,直至测试代码通过。
SoC原则(Separation Of Concerns)
SoC就是把一个软件功能分离为单独功能点。被分离的每个功能点有唯一的行为和数据,而且每个功能点都能够被其他所需要的类单独使用。通过这个原则,我们可以最大限度地实现代码重用、功能重用、模块重用。
讲述了一些基本的设计原则之后,再来看看Bob在《敏捷软件开发设计》[1]一书中提到的五个原则,简称S.O.L.I.D原则。
S.O.L.I.D原则融合了基本的原则,并且提出了更加具有可操作性的方法。
SRP(Single Responsibility Principle )
单一职责原则:就一个类而言,应该仅有一个引起它变化的原因。如果一个类承担的职责过多,就等于把这些职责都耦合在一起了。一个职责的变化可能会削弱或抑制这个类完成其他职责的能力。这个原则,不仅仅适用于类的设计上,还适用于接口以及模块的设计上。
OCP(Open-Closed Principle)
开放-封闭原则:软件实体(类,模块等)应该是可以扩展的,但是不可修改。只有在设计和开发中遵守OCP原则,才能避免在新加功能之后产生连锁反应。OCP关注的是灵活性:功能的改动是通过增加代码进行的,而不是修改现有的代码。一般来说,OCP是通过融合ISP(接口分离原则)和创建抽象来隔离后面同类型的变化的,LSP(里氏替换原则)使得这个目标成为可能。
LSP(Liskov Substitution Principle)
里氏替换原则:子类型必须能够替换掉它们的基类型。
ISP(Interface Segregation Principle)
接口分离原则:不应该强迫类实现它不需要的方法。如果一个接口中包含了很多不大而且不相关的方法,那么这个接口就必须要被分组,然后分离成多个接口,让实现接口的类只是去实现它所需要的方法。同时这也体现了在设计中,要尽量遵从SRP(单一职责原则)。
DIP(Dependency Inversion Principle)
依赖倒置原则:高层的模块不应该依赖于低层的模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。高层模块是指系统不经常发生变化的部分,是一个系统区别于其他系统的重要标志,它包含了系统的策略选择与业务模型。低层模块是指系统中经常发生变化的部分。