敏捷软件开发_设计原则<三>
单一职责原则(single responsibilities principle,SRP)
- 原理:一个类应该只有一个变化
- 分离职责:如果不耦合的职责那么很简单,如果两个职责耦合,将两个职责抽象为接口,通过继承两个接口将依赖关系抽离处理啊
开放封闭原则(open close principle,OCP)
- 软件实体(类,模块,函数等)应该是可以扩展的,但是不可修改
- 对扩展开放:当需求改变时,对模块可以扩展。
- 对修改封闭:对模块进行扩展时,不必改动模块的源代码或则二进制代码,
- 仅仅抽象出容易变化的部分。
里氏替换原则(liskov substitution principle,LSP)
- 子类型必须能够替换掉它的基类型。
依赖倒置原则(dependence inversion principle,DIP)
- 高层模块不应该依赖于底层模块,二者都应该依赖抽象
- 抽象不应该依赖细节,细节应该依赖抽象
为什么叫倒置,在传统软件开发中,总倾向于创建一些高层模块依赖底层模块,策略依赖细节的软件结构。一个良好的面向对象程序,对传统设计结构而言就被倒置了。
其实就是都依赖接口编程,高层依赖接口,细节依赖接口,这样模块的改动不会影响其他模块。比较好的模块设计:
模块和模块间的依赖都是依赖接口。
-
倒置不仅仅是依赖关系的倒置,也是接口所有权的倒置,通常会认为工具库应该拥有自己的接口,但其实应该是客户拥有接口,而它们的服务者应该是接口的派生。著名的 holly wood原则:“Don't call us, we'll call you”不要调用我们,我们会调用你,低层模块实现在高层模块中声明并被高层模块调用的接口
-
程序所有的依赖关系都应该终止与抽象
-
任何变量都不应该持有一个指向具体类的引用
-
任何类都不应该从具体类派生
-
任何方法都不应该重写它的任何基类中已经实现的方法。
接口隔离原则(interface segregation principle,ISP)
接口会被污染:
当借口的职责不再单一时,接口就很容易受到污染。
一个常见的例子:一个门,可能是关着也可能是开着,而且门类知道只是是开着还是关着。
常见的接口设计,现在需要实现自动报警,当门开着超过一定的时间就进行报警。常见的方法是关联timer类,实现报警。
这种方案就造成了接口污染,所有的门都必须依赖timeclient,同时还会出现门检测到时间超时,还未报警时,门关闭了,然后又被打开了,门变成了错误的报警
通过增加一个报警id,来区别每一次报警和客户端。
- 接口隔离原则:不应该强迫客户程序依赖并未使用的方法。
隔离接口
- 通过适配器原则,实现timer类对door类的引用隔离doorclient.这样仅仅增加了一个类,而将引用关系倒置。
创建一个派生自timer的timerclient对象,并把该对象请求委托给timerdoor。
这样就实现了timer和door的隔离,即使对timer进行更改也不会影响到door。timerdoor也不需要和timerclient一样的接口,
- 另一种方法是使用timerdoor来多重继承,door和timerclient,
这种方案没有多余的开销,只有当doortimeradapter对象所做的转换是必须的时候或则不同的时候需要不同的转换的时候,才需要使用适配器方法。
例子:
AMT的一个例子,输出信息要转换成不同的语言,输出信息要显示在桌面上,
把不同的事务处理方法封装在transaction上,这样每个事务的修改都会造成UI的修改,如果把接口分解成不通的单独接口,就可以避免
打包原则
大型系统的设计非常依赖于好的组件设计,这样每个团队只要关注于单个组件而不需要关注整个系统。
但类经常会和其他类发生依赖关系,这些依赖关系也会跨越组件的边界。
- 在向组件中分配类时应该依据什么原则
- 应该使用什么设计原则来管理组件之间的关系
- 组件的设计应该先于类(自顶而下),还是设计应该先于组件(自底而上)
- 组件的实体以什么方式存在
- 组件创建好后,用于何种目的
组件和组件间的依赖关系:不能依赖具体类。只能是具体依赖抽象,抽象依赖抽象。这样就可以将影响将至最低。
前三个原则来指导如何将类划分到包中,后三个原则来管理包之间的耦合(稳定)。组件之间的耦合越稳定就越好
重用发布等价原则(reuse release equivalence principle,REP)
重用粒度就是发布粒度:一个组件的重用粒度和发布粒度一样大,重用的任何东西必须被同时发布和跟踪,
重用性必然是基于组件的,所以可重用的组件必须包含可重用的类,因至少某些组件应该由一组可重用的类组成
一个类中的组件要么都是可重用的,要么都是不可重用的。
共同重用原则(common reuse principle , crp)
一个组件中所有的类都应该是共同重用的,如果重用了组件中的一个类,那么就要重用组件中的所有类。
这个原则可以帮助我们确定哪些类应该在一个组件中,相互之间没有紧密联系的类不应该在同一个组件中。
共同封闭原则(common closure principle,ccp)
组件中所有的类对同一种性质的变化应该是共同封闭的,一个变化若对一个封闭的组件产生影响,则将对该组件中所有的类产生影响,而对其他组件不产生影响。类似于单一职责原则。
无环依赖原则
在组件的关系图中不允许存在环。
解除依赖环的方法:提取抽象接口,通过实现接口来替换关联。关联和实现的依赖关系相反。
稳定依赖原则
朝着稳定的方向进行依赖。
被依赖的越多,该组件就越不可能改动,则越稳定。
稳定性度量:
稳定抽象原则
组件的抽象程度与其稳定性。
中间连接线称为主序列。
到主序列的距离:
越为0 越好
有了度量和标准就让我们划分组件吧!!!