软件构造 第六章第一节 可维护性的度量与构造原则

第六章第一节 可维护性的度量与构造原则

 

可维护性的常见度量指标

  • 可维护性
  • 除此之外,可维护性还有其他许多别名:可扩展性(Extensibility)、灵活性(Flexibility)、可适应性(Adaptability)、可管理性(Manageability)、支持性(Supportability)。总之,有好的可维护性就意味着容易改变,容易扩展。
  • 软件可维护性的五个子特性:
    • 易分析性。软件产品诊断软件中的缺陷或失效原因或识别待修改部分的能力。
    • 易改变性。软件产品使指定的修改可以被实现的能力,实现包括编码、设计和文档的更改。如果软件由最终用户修改,那么易改变性可能会影响易操作性。
    • 稳定性。软件产品避免由于软件修改而造成意外结果的能力。
    • 易测试性。软件产品使已修改软件能被确认的能力。
    • 维护性的依从性。软件产品遵循与维护性相关的标准或约定的能力。

 

  • 一些常用的可维护性度量标准:
    • 圈复杂度(CyclomaticComplexity):度量代码的结构复杂度。
    • 代码行数(Lines of Code):指示代码中的大致行数。
    • Halstead Volume:基于源代码中(不同)运算符和操作数的数量的合成度量。
    • 可维护性指数(MI):计算介于0100之间的索引值,表示维护代码的相对容易性。 高价值意味着更好的可维护性。
    • 继承的层次数:表示扩展到类层次结构的根的类定义的数量。 等级越深,就越难理解特定方法和字段在何处被定义或重新定义。
    • 类之间的耦合度:通过参数,局部变量,返回类型,方法调用,泛型或模板实例化,基类,接口实现,在外部类型上定义的字段和属性修饰来测量耦合到唯一类。
    • 单元测试覆盖率:指示代码库的哪些部分被自动化单元测试覆盖。

 

Maintainability Index (MI) 可维护性指数

 

内聚性

  • 又称块内联系。指模块的功能强度的度量,即一个模块内部各个元素彼此结合的紧密程度的度量。若一个模块内各元素(语名之间、程序段之间)联系的越紧密,则它的内聚性就越高。
  • 所谓高内聚是指一个软件模块是由相关性很强的代码组成,只负责一项任务,也就是常说的单一责任原则

耦合性

  • 也称块间联系。指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块的独立性则越差。模块间耦合高低取决于模块间接口的复杂性、调用的方式及传递的信息。
  • 对于低耦合,粗浅的理解是:一个完整的系统,模块与模块之间,尽可能的使其独立存在。也就是说,让每个模块,尽可能的独立完成某个特定的子功能。模块与模块之间的接口,尽量的少而简单。如果某两个模块间的关系比较复杂的话,最好首先考虑进一步的模块划分。这样有利于修改和组合。

 

最好的原则:

模块内高内聚,模块间低耦合

 

SOLID

(SRP) The Single Responsibility Principle 单一责任原则

(OCP) The Open-Closed Principle 开放——封闭原则

(LSP) The Liskov Substitution Principle Liskov 替换原则

(ISP) The Interface Segregation Principle 接口聚合原则

(DIP) The Dependency Inversion Principle 依赖转置原则

 

1.SRP

需要修改某个类的时候原因有且只有一个。换句话说就是让一个类只做一种类型责任,当这个类需要承当其他类型的责任的时候,就需要分解这个类。

反例:

正例:

2.OCP

对扩展性的开放:

模块的行为应是可扩展的,从而该模块可表现出新的行为以满足需求的变化

对修改的封闭:

但模块自身的代码是不应被修改的

扩展模块行为的一般途径是修改模块的内部实现

如果一个模块不能被修改,那么它通常被认为是具有固定的行为

正确示例:

3.LSP

LSP: 子类型必须能够替换其基类型

派生类必须

能够通过其基类的接口使用,客户端无需了解二者之间的差异

4.ISP

含义:客户端不应依赖于它们不需要的方法。换句话说,使用多个专门的接口比使用单一的总接口总要好。

 

客户模块不应该依赖大的接口,应该裁减为小的接口给客户模块使用,以减少依赖性。如Java中一个类实现多个接口,不同的接口给不用的客户模块使用,而不是提供给客户模块一个大的接口

上图是一个反例:

用户并不一样需要eat操作,因此最好把eat和work分开。

5.DIP

高层模块不应该依赖于低层模块,二者都应该依赖于抽象 

抽象不应该依赖于具体,具体应该依赖于抽象

简单的说,在copy中使用的是接口,把原先依赖于具体的reader和writer改成抽象的接口。

猜你喜欢

转载自www.cnblogs.com/masteryellow/p/9215067.html