《设计模式之禅》学习笔记(六)
第6章 开闭原则
开闭原则的定义:
Software entities like classes, modules and functions should be open for extension but closed for modifications.(一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。)
即,一个软件实体(模块、类、接口、方法)应该通过扩展来实现变化,而不是通过修改已有的代码来实现变化。
开闭原则是最基本的原则,是其他原则和设计模式的精神。
开闭原则的重要性:
- 开闭原则对测试的影响
所有已经投产的代码都是有意义的,并且都不受系统规则的约束。如果通过修改而不是扩展代码来应对需求变化,需要重新测试已经修改的代码。
一个方法的测试:
- 正常的业务测试
- 边界条件测试
- 异常测试
- 开闭原则可以提高复用性
在面向对象的设计中,所有的逻辑都是从原子逻辑组合而来的,而不是在一个类中独立实现一个业务逻辑。只有这样代码才可以复用,粒度越小,被服用的可能性就越大。
- 开闭原则可以提高可维护性
- 面向对象开发的要求
快速的应对变化,需要在设计之初就考虑所有可能变化的因素,然后留下接口。
需求变化的三种类型:
- 逻辑变化
可以通过修改原有类中的方法的方式来完成
- 子模块变化
通过扩展来应对
- 可见视图变化
可见视图是提供给客户使用的界面,该部分的变化一般会引起连锁反应,但还是可以通过扩展来完成变化,这就要看原来的设计是否灵活。
应对需求变化的原则:保持历史的纯洁性,不去修改历史。
应对需求变化的三种方法:
- 修改接口
不可靠的,该方案应该被直接否定。
- 修改实现类
该方法在项目有明确的章程或优良的架构设计时,是一个非常优秀的方法,但是仍有缺陷。
- 通过扩展实现变化
好方法,修改少,风险小。
最佳实践:
- 抽象约束
抽象是对一组食物的通用描述,没有具体的实现,也就可以跟随需求的变化而变化。
第一,通过接口或抽象类约束扩展,不允许出现在接口或抽象类中不存在public方法;
第二,参数类型、引用对象尽量使用接口或者抽象类,而不是实现类;
第三,抽象层尽量保持稳定,一旦确定即不允许修改。
- 元数据(metadata)控制模块行为
尽量使用元数据来控制程序的行为,减少重复开发。
元数据,就是用来描述环境和数据的数据,通俗地说就是配置参数,参数可以从文件获得,也可以从数据库中获得。
- 制定项目章程
章程中指定了所有人员都必须遵守的约定,对项目来说,约定优于配置。
- 封装变化
第一,将相同的变化封装到一个接口或抽象类中;
第二,将不同的变化封装在不同的接口或抽象类中。