软件维护
2022年11月18日 in 中国科学院大学
软件成本60%是维护,软件维护成本的60%是增强(修复缺陷占17%)
一、四类软件维护
- 纠正性维护(修复缺陷)
- 完善性维护(扩展功能)
- 适应性维护(变化运行环境)
- 预防性维护(改变软件结构提高未来可维护性)
二、遗留代码重构
- 遗留代码:仍满足用户需求,但软件积累了许多没有被当前设计文档涵盖的补丁(文档差、时间长、缺少充分测试)
- 重构:改变代码结构而不改变软件功能
问题1:在开发过程中会逐渐偏离原有设计文档
- 解决方案:非正式设计文档
- 高可读性单元(lo-fi UI、Cucumber、应用架构草图、类关系)
- Git日志文件(代码注释、设计评审存档)
问题2:改进遗留代码?
- 解决方案:
- a. 编辑并祈祷
- b. 测试覆盖
- 创建能够覆盖将要更新代码的测试
- 作为安全系统检查是否引起非计划行为改变
三、解决方式:敏捷方法提供帮助
|敏捷过程|
- 确定更改点
- 判断是否需要重构
- 对更改点代码测试(被测试了吗?能测试吗?)
- 被测试了:可以使用
- 没被测试但可以测试:使用BDD+TDD提高代码覆盖率
- 不可测试:重构
- 根据需要,增加测试、提高覆盖率
- 进行修改,使用已通过测试作为基石
- 进一步重构,让代码库变得更好
a. 被分配来修改遗留代码,哪个叙述会让你最高兴?——测试覆盖很好
许多原始的设计文档都是可用的?——在敏捷开发中可能不存在设计文档
b. 探索遗留代码:让代码run起来
c. 使用特征/表征测试来创建基准事实
测试用例是代码现阶段完成客观事实的规范,!但不要在现阶段做代码改进!
集成级别的特性测试:黑盒(使用Cucumber等工具执行命令式场景)
问题:相比于模块级或单元级特性测试,关于集成级特性测试,错误的说法是?——它们较少依赖对代码结构的详细了解
d. 如何写出好的注释
好的注释要比代码有更高级别的抽象(并非命令式告诉其他人代码执行过程)
四、对代码评价的定性指标
1. 定性:代码坏味(SOFA)
- Short:代码短
- One:代码只做一件事
- Few:代码参数较少
- 参数过多的问题:
- a.容易造成测试覆盖率不高、状态空间几何维度增加(测试用例越来越多)
- b.功能与其他方法之间的关联性越高(存根Stub越多)
- c.若存在bool参数,可能导致函数分支行为越来越多
- 参数过多的问题:
- Abstraction:抽象级别一致
- 复杂任务要分成小问题,小问题的封装程度要好
2. 定量
a. ABC复杂度
- 计算赋值(Assignment)、分支(Branch)、条件(Condition)
- score = A2+B2+C2 <= 20
b. 循环复杂度
- 线性独立路径数 CC = E – N + 2P(E:边, N:节点, P:连接组件)
- 度量指标(仅供参考)
五、重构
1.想法
- 从有1个或更多问题/坏味的代码开始
- 通过一系列的小步骤,转换成没有这些坏味的代码
- 用测试保护每一步
- 最小化改变测试为红色的时间
2.怎样去做
- 修复愚蠢的命名
- 提取方法
- 提取方法进行类封装
- 测试提取的类
- 关于单元测试的一些想法
SOFA哪个指导原则对单元级测试最重要?参数少(Few)
不是方法级重构的目标?消除错误
重构通常会导致对测试套件的更改(重构需要修改代码)
六、软件维护的P&D视角
- P&D花费1/3在开发上,2/3在维护上
- 开发团队 ≠ 维护团队
1. 维护流程
- a. 在现场/生产现场运行软件
- b. 与客户协作,与客户一起改进下一版本
- c. 响应变化(变更请求表单有票证跟踪)
2.对于需求变更
- a. 变更控制委员会
- b. 紧急变更请求
3.如何判断改进还是替换/再工程?
当软件老化,维护困难时,使用自动化工具进行升级
4.维护: P&D与敏捷的对比关系
任务 | P&D | 敏捷 |
---|---|---|
客户变更请求 | 变更请求表单 | 3x5卡片上的用户故事 |
变更请求成本/ 时间估计 | 由维护经理 | 开发团队评估点数 |
变更请求分类 | 变更控制委员会 | 开发团队与客户参与 |