软件构造 第六章 面向可维护性的构造随笔

6.1 Metrics and Construction Principles for Maintainability 维修性的度量和构造原则

首先,感谢有道翻译、谷歌翻译、百度翻译对本博文的大力支持。

Outline

  • Software Maintenance and Evolution 软件维护和发展
  • Metrics of Maintainability 可维护性指标
  • Modular Design and Modularity Principles 模块化设计与模块化原理
  • OO Design Principles: SOLID OO设计原则:可靠
  • OO Design Principles: GRASP OO设计原则:掌握

Software Maintenance and Evolution 软件维护和发展

Software Maintenance(软件维护):软件工程中的软件维护是指在软件产品交付后对其进行修改,以纠正故障,提高性能或其他属性

  • 软件维护同软件开发的各阶段均相关
  • 确定错误位置
  • 测试、修正和文档
  • 测试修改是否正确工作
  • 检查regression faults(回归性错误)
  • 记录所有更改

软件维护的种类:

  • 纠正性维护 25%——交付后对软件产品进行反应性修改,以纠正发现的问题
  • 适应性维护 21%——交付后对软件产品进行的修改,以保持软件产品在变化或变化的环境中可用
  • 完善性维护 50%——交付后增强软件产品的性能或可维护性
  • 预防性维护 4%——交付后对软件产品进行修改,以检测和纠正软件产品中的潜在故障,使其成为有效故障。

Software Evolution软件演进/发展

  • 软件进化是软件维护中使用的一个术语,指最初开发软件的过程,然后出于各种原因反复更新软件
  • 超过90%的典型系统成本发生在维护阶段,任何成功的软件都将不可避免地得到维护

软件需要适应不同的需求和环境

  • 制定了八项法律
  • 反馈系统Feedback System
  • 持续变化Continuing Change
  • 持续增长Continuing Growth
  • 质量下降Declining Quality
  • 复杂性增加Increasing Complexity
  • 自我调节Self Regulation
  • 保持组织稳定性Conservation of Organizational Stability
  • 保持熟悉Conservation of Familiarity

软件维护和发展的目标/责任

  • 软件维护和演进的目标:提高软件的适应性和适应性,保持软件的活力,即“持久软件(低熵软件)”
  • Linux内核演进的一个例子:可维护性指数
  • 维护不仅是维护人员的责任,也是设计和开发者的责任
  • 设计和开发者需要考虑软件未来的变化和扩展

面向可维护性的结构示例

  • 模块化设计和实现-低耦合和高内聚性
  • OO设计原则-扎实-掌握
  • OO设计模式-工厂方法模式、构建者模式-桥梁模式、代理模式-记忆模式、状态模式
  • 基于状态的构建(基于自动程序设计)
  • 表驱动的构建
  • GRA基于MMAR的结构

Metrics of Maintainability 可维护性指标

  • Maintainability可维护性-“修改软件系统或组件以纠正故障、提高性能或其他属性,或适应变化的环境的容易程度”。容易纠正错误和提高性能
  • Extensibility可扩展性-软件设计/实现考虑了未来的发展,并被视为扩展系统能力和实现扩展所需努力水平的系统性度量。易于增加功能
  • Flexibility灵活性-软件根据用户需求、外部技术和社会环境等容易改变的能力
  • Adaptability适应性-互动系统(适应性系统)的能力,能够根据获得的关于其用户及其环境的信息,使其行为适应个人用户。适用用户个性化需求
  • Manageability可管理性:如何有效、轻松地监控和维护软件系统,以保持系统的运行、安全和平稳运行
  • Supportability可支持性基于质量文档、诊断信息和知识渊博且可用的技术人员等资源,在部署后如何有效地保持软件的运行。发布后,软件受支持的程度

常用的可维护性指标

  • Cyclomatic Complexity循环复杂性
    • 衡量代码的结构复杂性
    • 独立路径的个数越多则需要更多的测试
  • 代码行-表示代码中的大约行数
    • 非常高的计数可能表示类型或方法正在尝试做太多的工作,应将其拆分
    • 它还可能指示类型或方法可能难以维护。
  • halstead volume:基于源代码中(distinct)运算符和操作数的数量的复合度量。运算符和操作数的数目的
  • 可维护性索引(MI)-计算介于0和100之间的索引值,该值表示维护代码的相对容易程度。高值意味着更好的可维护性。它的计算基于:
    • Halstead volume(hv)
    • cyclomatic complexity(cc)
    • 每个模块的平均代码行数(loc)
    • 每个模块的注释行百分比(com)
  • 继承深度-指示扩展到类层次结构根的类定义数。层次结构越深,就越难理解在哪里定义或/和重新定义特定的方法和字段
  • 类耦合-通过参数、局部变量、返回类型、方法调用、通用或模板实例化、基类、接口实现、在外部类型上定义的字段和属性修饰来测量与唯一类的耦合
    • 良好的软件设计要求类型和方法具有高内聚性和低耦合性
    • 高耦合意味着设计很难重用和维护,因为它与其他类型有许多依赖关系
  • 单元测试覆盖率-表示自动单元测试覆盖了代码库的哪个部分

Modular Design and Modularity Principles 模块化设计与模块化原理

  • 将程序的功能分散到独立可交互的模块中
  • 模块化是高层的功能分解技术
  • 在结构化编程中是如何根据控制流分解代码
  • 在OOP中是指对象中数据的使用方式

Modular programming模块化编程

  • 设计的目标是将系统划分为模块,并在组件之间分配责任,方式是:
    • 模块内的高内聚性
    • 模块之间的松散耦合
  • 模块化降低了程序员在任何时候必须处理的总复杂性,假设:
    • 功能被分配到模块中,将相似的功能组合在一起(关注点分离)
    • 模块之间有小的、简单的、定义明确的接口(信息隐藏)
  • 凝聚力和耦合原则可能是评估设计可维护性的最重要设计原则。

Five Criteria for Evaluating Modularity 评价模块性的五个标准

  • Decomposability (可分解性) – 较大的组件是否分解成较小的组件?
  • Composability (可组合性) – 较大的部件是由较小的部件组成的吗?
  • Understandability (可理解性) – Are components separately understandable?
  • Continuity (可持续性) – Do small changes to the specification affect a localized and limited number of components? 对规格说明的的改动,其影响是否是局部和有限的
  • Protection (保护性) – Are the effects of run-time abnormalities confined to a small number of related components?运行时异常的影响是否仅限于少数相关组件?
  1. Decomposability (可分解性):将问题分解为各个独立解决的子问题–目标:保持依赖关系显式化和最小化–示例:自上而下的结构设计
  2. Composability (可组合性): 可容易的将模块 组合起来形成新的系统–目标:使模块可在 不同的环境下复用 – Example: Math libraries; UNIX command & pipes
  3. Understandability (可理解性): Individual modules understandable by human reader (每个子模块都可被系统设计者容易的理解) – Example: Unix shell such as Program1 | Program2 | Program3 – Counter-example: Sequential Dependencies (A →B → C)
  4. Continuity (可持续性):规格说 明小的变化将只影响一小部分模块,而不会影响整个体系结构,模块提供的所有服务应该通过统一标识提供
  5. Protection (保护性):运行时的不正常将局限于小范围模块内

**Five Rules of Modularity Design 模块化设计的五大原则 **

RuleMeaningImpact on
Direct Mapping直接映射模块的结构与现实世界中问题领域的结构保持一致可持续性 可分解性
Few Interfaces 尽可能少的接口模块应尽可能少的与其他模块通讯可持续性、保护性、可理解性、可组合性
Small Interfaces 尽可能小的接口如果两个模块通讯,那么它们应交换尽可能 少的信息可持续性 保护性
Explicit Interfaces 显式接口当A与B通讯时,应明显的发 生在A与B的接口之间可分解性、可组合性、可持续性、 可理解性
Information Hiding 信息隐藏经常可能发生变化的设计决策应 尽可能隐藏在抽象接口后面可持续性

Coupling and Cohesion 耦合和内聚
Coupling:

  1. 耦合是模块之间依赖性的度量。如果一个模块中的更改可能需要另一个模块中的更改,则两个模块之间存在依赖关系
  2. 模块之间的耦合程度由以下因素决定:–模块之间的接口数量–接口复杂性,通信的复杂性。

Cohesion:

  1. 内聚是衡量一个模块的功能或职责有多强关联的指标
  2. 如果一个模块的所有要素都朝着同一个目标努力,那么它具有很高的内聚。

Coupling and Cohesion:
最佳设计在模块内具有高内聚性(也称为强内聚性),在模块之间具有低耦合性(也称为弱耦合)

OO Design Principles: 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 依赖转置原则
Open Closed Principle(OCP)开闭原则
  • 对扩展是开放的 ,对修改是封闭的,应通过继承和组合改变/扩展功能
  • 当软件系统必须支持一组替代方案时,系统中应该有且只有一个 模块知道方案的详尽列表
Liskov substitution principle (LSP) Liskov替代原则
  • 关注的是“操作”的可替换性
  • 子类型必 须能够替换其基类型
Interface segregation principle (ISP) 接口隔离原则

客户不应该被迫依赖他们 不使用的接口,即保持小接口。

Dependency inversion principle (DIP) 依赖转置原则
  • 高层模块不应该依赖于低层 模块,二者都应该依赖于抽象
  • 抽象不应该依赖于实现细节,实现细节应该依赖于抽象
    Advantages:
  • 类的契约形式化
  • 通过前置和后置条件, 清晰定义子程序的功能
    Try Design for Testing:
  • 形成测试友好的设计
OO设计的两大武器

▪ 抽象(abstraction):模块之间通过抽象隔离开来,将稳定部分和容易 变化部分分开

  • LSP:对外界看来,父类和子类是“一样”的;
  • DIP:对接口编程,而不是对实现编程,通过抽象接口隔离变化;
  • OCP:当需要变化时,通过扩展隐藏在接口之后的子类加以完成,而不要修 改接口本身。
    ▪ 分离(Separation): Keep It Simple, Stupid (KISS)
  • SRP:按责任将大类拆分为多个小类,每个类完成单一职责,规避变化,提 高复用度;
  • ISP:将接口拆分为多个小接口,规避不必要的耦合。
    ▪ 归纳起来:让类保持责任单一、接口稳定。

OO Design Principles: GRASP

通用责任分配软件模式 (原则)
GRASP模式是帮助人们理解基本对象设计,并以一种有条理、合理、可解释的方式应用设计推理的学习辅助工具。这种理解和使用设计原则的方法是基于将责任分配给Class的模式

  • 对象的责任:对象的义务

  • 拥有信息的类负责相应的责任

  • 将责任 分配给中间对象,以避免直接耦合

  • Knowing: 掌握

  • Doing: 操作

GRASP是由什么组成的?
▪ ▪ ▪ ▪ ▪ ▪ ▪ ▪

  • 控制器 Controller
  • 信息专家 Information expert
  • 创造者 Creator
  • 低耦合 Low coupling
  • 高内聚 High cohesion
  • 间接的 Indirection
  • 多态性 Polymorphism
  • 受保护的变体 Protected variations
  • 纯虚构 Pure fabrication

Polymorphism多态性
问题:如何根据类型处理备选方案?如何创建可插拔的软件组件?
解决方案:当相关的替代方案或行为因类型(类别)而异时,使用多态操作将行为人的责任分配给行为发生变化的类型。
▪根据多态性原则,将根据类型定义行为变化的责任分配给发生这种变化的类型。
▪这是通过多态操作实现的。
▪类型的用户应该使用多态操作,而不是基于类型的显式分支。

Protected variations 防止变异
Problem: 使对象或系统的内部不稳定性不会对其他元素产生不良影响
Solution:
确定将会发生的变化
分配责任以创建稳定的接口

Pure fabrication 纯虚构
Problem: 无法依靠专家模式实 现高内聚和低耦合时
Solution: 设计虚构的类实现高内聚低耦合和复用

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值