软件设计原则
最近在面试的过程中,有遇到相关的问题。仅在此做个简单的整理。
因涉及原则过多仅对一部分原则进行罗列。
喜欢这部分内容的朋友,欢迎阅读原著《软件设计重构(Refactoring for Software Design Smells)》
1.抽象原则
抽象原则倡导通过精简和概括来简化实体:精简指的是删除不必要的细节,而概括指的是找出并定义重要的通用特征。
2.非循环依赖原则
非循环依赖原则(ADP)指出,包之间的依赖关系不可以形成循环。ADP主要针对的是包之间的关系,通常认为它只适用于架构级,但类级循环依赖也不可取。依赖循环带来的限制如下:必须同事使用、测试、开发和理解循环涉及的所有实体。存在循环依赖时,修改一个包/类(假设为A)时。可能必须修改循环涉及的其他包/包(假设为B);然而由于循环的特征,修改B可能引发连锁反应,波及最初设计的包/类(即A)。在复杂的软件系统中,涉及面广的间接依赖通常难以发现,而它们正是引发微妙bug的温床。总之,不要在包/类之间引入直接/间接依赖循环。
3.不自我重复原则
不自我重复(don't Repeat Yourself, DRY)原则规定,对每个知识点,系统中都只有一个明确而权威的表示。这个原则倡导“单一事实源”理念,适用于所有软件工作,包括文档、架构和设计、测试代码和源代码。在详细设计中,设计实体和代码的重复可表现为类型名重复或实现重复。
有意或无意的重复是微妙缺陷的常见温床,因此在软件系统中应避免任何形式的重复。
4.封装原则
封装倡导通过隐藏抽象的实现细节和隐藏变化等方法实现关注点分离和信息隐藏。
5.信息隐藏原则
信息隐藏原则倡导找出棘手活可能变化的设计决策,并创建合适的模块或类型对其他模块或类型隐藏这些决策。这种设计方法有助于在设计决策发生变化时,避免对程序或其他部分做大量修改。在本书中,信息隐藏原则还意味着抽象的共有接口只暴露其内容,而不暴露其方式。
通过遵循这种原则,可降低抽象实现细节变化对客户代码的印象,从而改善软件设计的可改变行和可扩展性。
6.保持简单原则
保持简单(Keep It Simple Silly,KISS)原则指出,简单是软件系统设计的重要目标,应避免引入不必要的复杂性。本书采用的是Tony Hoare对KISS原则的定义:……创建软件设计的方式有两种:
让它简单到明显没有缺陷
让它复杂到没有显而易见的缺陷
7.里氏替换原则
里氏替换原则(LSP)的正式定义如下:……这里要提供的是类似于下面的替换特征:对于每个类型为T的对象o2,都有类型为S的对象o1,使得在以T定义的所有程序P中将对象o2替换为o1是,程序P的行为不会发生变化,那么S就是T的子类型。LSP的一种非正式定义如下:必须能通过基类接口使用派生类,而不要求用户知道这种差别。换而言之,所有子类型都必须至少提供超类型承诺的行为,且对每个超类型的引用,都可替换为子类型的实例。
8.层次结构原则
层次结构原则倡导使用分类、概括、替换、排序等方法以层次方式组织抽象。
9.模块化原则
模块化原则倡导通过集中和分解等手法创建高内聚、低松散的抽象。
10.开闭原则
开闭原则(OCP)指出,类型应对扩展开放,对修改关闭。具体地说,模块应该能够在不修改其他代码的情况下支持新需求。Bertrand Meyer指出,类型的实现编写好后,除非为修复bug,否则不能再修改它;要支持任何新的需求,都必须通过扩展类而不是修改类的代码来实现。
11.单一责任原则
Robert C. Martin指出,绝不应有多个导致类需要修改的原因。每项职责都是一个变化轴,因此每种变化都应只影响一项职责。类承担了多项职责时,要理解每项职责及其与类的其他职责的关系等,需要更多的时间和精力。这会给可理解性带来负面影响。类外,修改一个成员可能影响类的其他不相关职责,导致类难以维护。
12.变化封装原则
变换封装原则倡导一种信息隐藏方式,建议将可能发生变化的概念封装起来。很多设计模式都替换了这种设计原则,其中包括策略模式、桥梁模式和观察者模式。