7.7 软件维护
软件维护不是“开发结束以后偶尔修个 bug”。在一个软件的生命周期里,维护往往持续时间最长、耗费成本最大。开发可能一两年完成,但系统可能运行五年、十年;期间会遇到用户新需求、运行环境变化、人员流动、技术升级、隐藏缺陷暴露等问题。
为什么维护是生命周期中最重的阶段
软件交付后就进入真实环境。真实环境比开发环境复杂得多:用户行为不可控,数据规模会增长,硬件和操作系统会升级,政策和业务规则会变化,原开发人员也可能离开。维护阶段要在“不破坏已有系统”的前提下持续修改,因此成本很高。
flowchart LR
D["开发阶段<br/>需求-设计-编码-测试"] --> R["交付运行"]
R --> M["维护阶段<br/>修错、扩展、适配、预防"]
M --> R
M -.长期成本.-> C["人员交接<br/>文档理解<br/>版本控制<br/>回归测试"]维护工作的难点不只是“改代码”,而是理解旧系统、判断影响范围、保证修改后的系统仍然稳定。
四类维护
| 维护类型 | 触发原因 | 核心判断 | 例子 |
|---|---|---|---|
| 改正性维护/更正性维护 | 已经发现错误 | 修复已经发生或用户已遇到的缺陷 | 登录偶发失败,修复认证逻辑 |
| 预防性维护 | 潜在错误尚未爆发 | 在问题发生前降低未来风险 | 千年虫前把两位年份改为四位年份 |
| 完善性维护/改善性维护 | 用户提出新需求或希望更好用 | 增加功能、改善性能、提升体验 | 新增报表功能,优化算法提高响应速度 |
| 适应性维护 | 外部环境变化 | 适应硬件、操作系统、数据环境、政策、市场等变化 | 适配新版操作系统,支持新税法规则 |
考试最常考的是“给场景判断维护类型”。做题时不要只看“改了什么”,还要看“为什么改”。
改正性维护与预防性维护
这两类都和错误有关,但时间点不同。
| 对比项 | 改正性维护 | 预防性维护 |
|---|---|---|
| 错误是否已经发生 | 已发生或已被用户发现 | 还没发生,但可以预见 |
| 修改目的 | 消除当前故障 | 避免未来故障或降低未来维护难度 |
| 典型表述 | 修复 bug、纠正错误、故障处理 | 提前打补丁、重构、消除隐患 |
| 风险来源 | 已暴露缺陷 | 潜在缺陷、技术债、未来边界条件 |
课程里用“千年虫”解释预防性维护很贴切。早期系统用两位数表示年份,99 可理解为 1999,但 00 到来时就可能被误解为 1900。21 世纪到来之前,这个错误还没有在运行中爆发;提前修改年份处理逻辑,就是预防性维护。若错误已经导致用户业务失败,再修就是改正性维护。
完善性维护与适应性维护
这两类容易混淆。完善性维护强调系统本身变得更强、更快、更好用;适应性维护强调外部环境变了,软件为了继续运行或合规而调整。
| 场景 | 类型 | 判断原因 |
|---|---|---|
| 用户希望增加导出 Excel 功能 | 完善性维护 | 新增功能 |
| 原查询响应慢,修改算法提升速度 | 完善性维护 | 性能改善 |
| 操作系统升级后软件不能运行,修改兼容性 | 适应性维护 | 运行环境变化 |
| 法规要求新增实名校验字段 | 适应性维护 | 政策环境变化 |
| 数据库从 MySQL 迁移到 PostgreSQL | 适应性维护 | 数据环境变化 |
如果题干同时出现“新增功能”和“适配新环境”,要看主要驱动。如果新增功能是为了满足政策、操作系统、数据环境变化,通常按适应性维护理解。
可维护性由什么决定
可维护性不是维护阶段才出现的质量。设计、编码、文档和测试都会决定后期好不好维护。
| 因素 | 含义 | 为什么重要 |
|---|---|---|
| 可理解性 | 代码、设计和文档容易读懂 | 接手人员能快速判断系统如何工作 |
| 可修改性 | 修改局部不容易引发连锁反应 | 降低变更风险和成本 |
| 可测试性 | 修改后容易验证是否正确 | 支撑回归测试和缺陷定位 |
| 稳定性 | 修改后系统不易产生意外副作用 | 避免“修一个坏三个” |
| 文档完备性 | 需求、设计、接口、测试记录清楚 | 方便追溯和人员交接 |
高内聚、低耦合、清晰接口、版本管理、自动化测试、规范文档,本质上都是为了提高可维护性。
维护工具
课程里补充了维护工具的考点。题目可能问“下列哪个不属于软件维护工具”。
| 工具/活动 | 是否常作为维护工具 | 说明 |
|---|---|---|
| 版本控制 | 是 | 记录软件升级和变更历史 |
| 文档分析 | 是 | 维护旧系统前要理解需求、设计和实现 |
| 逆向工程 | 是 | 从已有系统反向获取模型、设计或需求信息 |
| 配置管理 | 不宜简单归为维护工具 | 配置管理贯穿整个生命周期,不只属于维护阶段 |
逆向工程要特别注意:正常开发是从需求到模型再到系统;逆向工程是从现有系统反向抽取模型、设计和需求,因此常出现在运行维护之后。
技术迭代中的维护取舍
维护并不总是“旧系统继续打补丁”。有时旧技术会被新技术替代,原因通常是旧方案维护成本过高或无法适应新环境。
| 旧方案 | 优势 | 局限 | 新方案替代原因 |
|---|---|---|---|
| 单体应用手工部署 | 简单、早期成本低 | 变更影响大,回滚困难,扩展不灵活 | 容器化和自动化部署降低发布与回归成本 |
| 硬编码业务规则 | 实现快,逻辑直观 | 政策变化时必须改代码 | 规则引擎或配置化让适应性维护更快 |
| 无自动化回归测试 | 初期投入少 | 每次修改都靠人工验证,漏测风险高 | 自动化测试支撑频繁迭代 |
| 缺少版本控制 | 小团队临时开发方便 | 无法追溯修改,协作风险极高 | Git 等版本控制成为维护基础设施 |
这些不是软考维护类型的直接分类,但能帮助理解为什么维护成本会推动工程实践迭代。
例题
本节小结
软件维护是生命周期中最长、成本最高的阶段。四类维护按原因区分:改正性修已发生错误,预防性防未来错误,完善性增加功能或改善性能,适应性应对外部环境变化。做题时优先抓“修改原因”,再看“修改内容”。