包的设计原则
- 包的设计.
- 通过把类组织成package,可以在更高层次的抽象上理解设计.通过包来管理软件的开发和发布.
- 由于类之间的相互依赖关系,包之间会产生依赖关系.包的依赖关系展示了APP的高层组织结构.
- 粒度:内聚性."自顶向上"的将类划分到包中
- Reuse-Release Equivalence Priciple(REP).
- 重用的粒度就是发布的粒度.
- 重用类库时,我们要求author维护Code,同时在接口和功能改变时通知我们(同时我们有拒绝改变的权利).
- 重用性必须基于包,可重用的包必须包含可重用的类.包中的所有类应该对于同一类用户来说都是可重用的.
- Common-Reuse Principle(CRP)
- 趋向于共同重用的类应该属于同一个包.
- 如果依赖于一个包,那么应该依赖于该包中的所有类.否则将要进行不必要的重新验证和发布(当不依赖的部分变化时).
- 相互之间没有紧密联系的类不应该在同一包内.
- Common-Closure Principle(CCP)
- 一个包不应该包含多个引起变化的原因(SRP的包规定).
- 通常,可维护性是重于可重用性的.应该将可能由于同样的原因而更改的类共同聚集在一个包内.
- 选择包中的类时,要考虑可重用性与可开发性之间的反作用力.
- Reuse-Release Equivalence Priciple(REP).
- 稳定性:耦合性.
- Acyclic-Dependencies Principle(ADP)
- 包的依赖关系图中不允许出现环.
- Weekly Build.
- 用于中等规模项目,平时在私有拷贝上Code.周五Build.但是之后,为了保持效率,就必须要不断地延长构建周期.
- Eliminating Dependency Cycles
- 把开发环境划分成可发布的包.分别开发各个包.以小规模增量的方式进行集成.
- 包依赖关系图中环依赖造成影响
- 环上的所有包会共同组成一个大包,彼此之间的发布要完全一致.
- 测试一个包时需要引入和编译的包的数量会增长.使用UT可以提现.
- 存在环时,很难确定包构建的顺序.
- 解除依赖环
- 抖动:Jitters.
- 随着APP的增长,包的依赖关系结构会抖动(需求更改时)和増长(新增Package).
- Acyclic-Dependencies Principle(ADP)
- 自顶向下的设计
- 包的依赖关系不能描绘APP的功能.它只是APP可构建性的映射图.
- 开始时,不设计包的结构.包结构是随着系统的增长,变化而逐步演化的.
- 当类越来越多时,开始关注CCP,将可能会一同变化的类放在一个包中.
- 之后,使用CRP来知道可重用元素的包组合.
- 最后,当环出现时,使用ADP.从而会导致包的抖动.
- 包的依赖关系是和系统的逻辑设计一起增长和演化的.
- Stable-Dependencies Principle(SDP)
- 朝着稳定的方向进行依赖.
- 为了可维护性,易变性是必须的.对某些变化敏感的包,可以设计成可变的
- 对于一个期待可变的包,不应该让一个难以更改的包依赖于它.否则,它也会变成不可变的.
- 软件的反常特性:对于一个易变的包,创建一个对它的依赖就可以使其变得难以更改.
- Stability
- 稳定性和更改所需的工作量有关.
- 稳定性度量
- 输入耦合度(A:外部依赖于内部),输出耦合度(E). 不稳定性(I). I= E/(A+E).
- [0,1].0代表具有最大的稳定度.
- 一个包的I值应该大于它所依赖的包的I值.I顺着依赖的方向减小.
- 并非所有的包都应该是稳定的.
- 应该把封装系统高层设计的软件放入稳定的包中(I=0).
- 同时,为了让其有灵活性,经受得起变化.使用抽象类.
- Stable-Abstraction Principle(SAP)
- 包的抽象程度应该和其稳定程度一致.
- 一个稳定的包应该是抽象的,这样稳定性不会使其无法扩展.
- 一个不稳定的包应该是具体的,不稳定性使其内部的具体代码易于更改.
- SAP+SDP构成了包的DIP原则.依赖应该朝着稳定的方向进行+稳定性意味着抽象性=>依赖应该朝着抽象的方向进行.
- 包的灰度(shades of grey):允许包是部分抽象,部分稳定的.
- 包抽象性度量:A=a/c.抽象类的数目/类的总数.
- Pain区域
- DB Schema.很高的易变性,同时非常具体,高度被依赖.所以APP和DB之间的接口很难定义.对DB Schema的更新很痛苦.
- 工具库.string.
- 包的抽象程度应该和其稳定程度一致.
[Agile Software Development(Principles,Patterns,and Pracitices)]