软件构造——可维护性

本文是对软件构造课程软件可维护性相关内容的整理与理解,使用的编程语言为 Java。可维护性,也就是指软件发生变化时,是否可以以很小的代价适应变化。

软件维护和演化

软件维护

软件维护(software maintenance)是指软件产品在出厂后为了纠正故障、提高性能或其他属性而进行的修改。

软件维护有如下几种:

  • 纠错性维护 (corrective maintenance):25%。在交付后对软件产品进行的反应性修改,以纠正发现的问题。
  • 适应性维护 (adaptive maintenance):21%。在交付后对软件产品进行的修改,以保持软件产品在变更或变化的环境中可用。
  • 完善性维护 (perfective maintenance):50%。在交付后对软件产品的增强,以提高性能或可维护性。
  • 预防性维护 (preventive maintenance):4%。在软件产品交付后对其进行修改,以便在软件产品的潜在故障变为有效故障之前发现并纠正它们。
    软件演化

软件发展(software evolution)是软件维护中的一个术语,指的是软件从最初的开发到后来由于各种原因不断更新的过程。一个典型系统超过 90% 的成本是在维护阶段产生的,任何成功的软件都不可避免地要进行维护。

维护不仅是运维工程师的任务,也是软件设计人员和开发人员的潜在任务。对于他们来说,必须在设计和构造阶段考虑软件未来的潜在变化与扩展。这样,灵活和可扩展的设计与结构就被综合考虑进来。这就是所谓的软件构造的“可维护性”、“可扩展性”和“灵活性”。

面向可维护性的软件构造有如下的例子:

  • 模块化设计与实现:低耦合高内聚
  • OO 设计原则:SOLID、GRASP
  • OO 设计模式
  • 基于语法的构造技术

可维护性的指标

可维护性的许多名称

  • 可维护性(maintainability):修改软件系统或组件以纠正错误、提高性能或其他属性,或适应变化的环境的易用性
  • 可扩展性(extensibility):软件设计与实现考虑到未来的发展,并被视为扩展系统的能力和实现扩展所需的工作水平的系统度量。
  • 灵活性(flexibility):软件能够根据用户需求、外部技术和社会环境等进行更改。
  • 可适应性(adaptability):交互式系统(自适应系统)的一种能力,它可以根据所获得的关于用户及其环境的信息来调整其行为以适应单个用户。
  • 可管理性(manageability):究竟能够多有效且容易地监控和维护软件系统,以确保系统的表现、安全及平稳运行。
  • 支持性(supportability):软件在部署后能够多有效地保持运行,这取决于资源,包括质量文档、诊断信息和有知识的和可用的技术人员。

一些常用的可维护性指标

圈复杂度

圈复杂度(cyclomatic complexity)衡量代码的结构复杂性。它是通过计算程序流中不同代码路径的数量来创建的。一个具有复杂控制流的程序将需要更多的测试来实现良好的代码覆盖,并且将更不容易维护。

代码行数

代码行数(lines of code)指示代码中的大致行数。一个非常高的代码行数可能表明一个类型或方法试图做太多的工作,应该被拆分。它还可能表明类型或方法可能很难维护。

可维护性指数

可维护性指数(maintainability index,MI)是一个在 0—100 的值,表示相对容易维护代码的程度。更高的值意味着更好的可维护性。计算依据如下:

  • Halstead 体积(HV)
  • 圈复杂度(CC)
  • 每个模块的平均代码行数(LOC)
  • 每个模块注释行所占的百分比(COM)

M I = 171 ? 5.2 ln ? ( H V ) ? 0.23 C C ? 16.2 ln ? ( L O C ) + 50.0 sin ? 2.46 ? C O M MI = 171 – 5.2 ln(HV) – 0.23 CC – 16.2 ln(LOC) + 50.0 sin sqrt{2.46 * COM} MI=171?5.2ln(HV)?0.23CC?16.2ln(LOC)+50.0sin2.46?COM ?

继承的层次数

继承的层次数(depth of inheritance)指继承树中到根的定义的类的数量。层次结构越深,就越难以理解特定的方法和字段是在哪里定义或重新定义的。

类之间的耦合度

类之间的耦合度(class coupling)通过参数、局部变量、返回类型、方法调用、泛型或模板实例化、基类、接口实现、定义在外部类型上的字段和属性装饰来度量到特定类的耦合。好的软件设计要求类型和方法应该具有高内聚性和低耦合性。高耦合表明设计很难重用和维护,因为它对其他类型有许多相互依赖关系。

单元测试的覆盖度

单元测试的覆盖度(unit test coverage)指自动化单元测试覆盖了代码的哪些部分。

模块化设计与模块化原理

模块化编程

模块化编程是一种强调将程序的功能分离成独立的、可互换的模块的设计技术,这样,每个模块只包含执行所需功能的那个方面所需要的所有东西。

设计的目标是将系统划分为模块,并按如下方式在各组件之间分配职责:

  • 模块内的高内聚
  • 模块间的低耦合

模块化降低了程序员在一个时候必须处理的总复杂度,前提是:

  • 将函数分配给模块,将类似的函数分组在一起(关注点分离)。
  • 模块之间有小的、简单的、定义良好的接口(信息隐藏)。

内聚性和耦合原则可能是评估设计可维护性的最重要的设计原则。

评估模块化的五个标准

  • 可分解性(decomposability):更大的组件是否被分解成更小的组件了/li>
  • 可组合性(composability):更大的组件是否是由更小的组件组成的/li>
  • 可理解性(understandability):组件是否可以单独地理解/li>
  • 可持续性(continuity):对规约的微小更改是否会影响本地化的有限数量的组件/li>
  • 保护性(protection):运行时异常的影响是否仅限于少数相关组件/li>

模块化设计的五个原则

  • 直接映射(direct mapping)
  • 尽可能少的接口(few interfaces)
  • 尽可能小的接口(small interfaces)
  • 显式接口(explicit interfaces)
  • 信息隐藏(information hiding)

耦合和内聚

耦合(coupling)是模块之间依赖关系的度量。如果一个模块中的更改可能需要另一个模块中的更改,则两个模块之间存在依赖关系。模块之间的耦合程度由以下因素决定:

  • 模块间接口数量
  • 每个接口的复杂性(由通信类型决定)

内聚(cohesion)%是一个模块的功能或职责之间的关联程度的度量。如果模块的所有元素都朝着相同的目标工作,那么模块就具有高度的内聚性。

最好的设计在模块内具有高内聚性(也称为强内聚性),模块之间具有低耦合性(也称为弱耦合性)。

面向对象的设计原则:SOLID

单一责任原则

“一个类的改变不应该有多于一个的原因”,也就是说,一个类应该专注于做一件事,而且只做一件事。这就是单一责任原则(single responsibility principle,SRP)。“仅仅因为你能做,并不意味着你应该做。”在这里,责任就是“变化的原因”。不应有多于一个的原因使得一个类发生变化。一个类,一个责任。

如果一个类包含了多个责任,那么将引起不良后果:

  • 引入额外的包,占据资源。
  • 导致频繁的重新配置、部署等。

SRP 是最简单的原则之一,却也是最难正确把握的原则之一。

开放—封闭原则

开放—封闭原则(open-closed principle,OCP)可以从两方面理解:

  • 类应该对扩展开放。模块的行为应是可扩展的,从而该模块可表现出新的行为以满足需求的变化。
  • 对修改封闭。模块的源代码是不可侵犯的,任何人都不允许对它进行源代码更改。扩展模块行为的正常方法是对该模块进行更改。不能更改的模块通常被认为具有固定的行为。

OCP 原则关键的解决方案:抽象技术。“软件实体(类、模块、函数等)应该对扩展开放,但对修改关闭”,也就是说,使用继承和组合(委托)来改变类的行为。

Lisklov 替换原则

Lisklov 替换原则(liskov substitution principle,LSP)可以表述如下:“使用指向基类的指针或引用的函数必须能够在不知情的情况下使用派生类的对象”,也就是说,在使用子类代替基类时,子类应该表现良好。(子类型必须能够替换其基类型)派生类必须可以通过基类接口使用,而不需要客户机知道其中的区别。

接口隔离原则

这就是接口隔离原则(interface segregation principle,ISP)可以表述如下:“不应该强迫客户端依赖于他们不使用的接口”,也就是说,要保持接口小。

不要强迫类实现它们无法实现的方法;不要用太多的方法污染接口;避免“臃肿的”接口。

依赖转置原则

依赖转置原则(dependency inversion principle,DIP)可以表述如下:高级模块不应该依赖于低级模块,两者都应该依赖于抽象:抽象不应该依赖于细节;细节应该依赖于抽象。应该使用大量的接口和抽象。

文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览91648 人正在系统学习中

来源:SY-Liu

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年5月11日
下一篇 2022年5月11日

相关推荐