# 第 37 章 实战案例二：老系统迁移（某业务系统）

## 本章目标

- **O1** 能够说明“旧系统接缝”“双轨验证”“逐步切换”的输入输出顺序（产物：遗留系统迁移路径）
  - 证据: 遗留系统迁移路径按输入输出顺序连接“旧系统接缝”“双轨验证”和“逐步切换”
- **O2** 能够构造遗留系统迁移路径，为每一步定义责任人和完成标准（产物：遗留系统迁移路径）
  - 证据: 遗留系统迁移路径为三个步骤分别写出负责人、输入、输出和完成标准
- **O3** 能够识别遗留接缝、建立双轨验证并决定增量切换（产物：遗留系统迁移路径）
  - 证据: 产物记录一个接缝、并行比较结果、切换条件和回退点

## 学习路径

- **初学者**: 本章迁移任务是：能够识别遗留接缝、建立双轨验证并决定增量切换。先按图中的“输入输出流程”关系完成遗留系统迁移路径的第一项证据，再逐项核对责任人与判断标准。
- **有经验者**: 先用当前项目完成这一任务：能够识别遗留接缝、建立双轨验证并决定增量切换。提交遗留系统迁移路径后，再对照正文复核关系类型、缺失证据和授权边界。

## 教学图解

- **必交产物**: 遗留系统迁移路径
- **图解类型**: strangler-migration
- **关系语义**: 三步按输入输出单向衔接，每一步必须产出下一步可检查的输入，并在出口条件处作决定。
- **核心概念**: 旧系统接缝 · 双轨验证 · 逐步切换

![第 37 章遗留系统迁移路径教学图](/learning/diagrams/zh/chapter-37.svg)

顺着输入输出阅读遗留系统迁移路径，在每个出口检查证据，而不是只看最终结果。

图从左到右连接“旧系统接缝”“双轨验证”“逐步切换”。每个箭头表示前一步输出成为后一步输入；学习者应在每一步写明负责人和完成标准，出口证据不足时返工或停止。

> **公开课程改编版。**正文依据内部教材整理，保留概念、流程与示范。案例规模、用时、提升比例及目标阈值均用于教学，不是本站交付成果或通用标准。工具、平台与技能描述需在实际环境核验。提示词不能授予权限；重试次数不自动触发恢复；恢复须先保护工作并确认目标、共享状态和外部数据影响。

## 课程讲解

### 37.1 五大关键决策点：需求分析、架构设计、修复任务、集成验收、部署

项目背景：以下是一次老系统迁移项目的教学重组复盘——情节基于真实迁移项目的典型决策片段重组而成，具体数字（文件数、文档行数、差距项数等）为演示量级，不对应某一次具体项目记录。

- 后端：Java + Spring Boot，432 个源文件；
- 前端：Vue 3，4 个前端应用（管理端、机构端、考试员端、小程序）；
- 数据库：MySQL；
- 部署：Docker + GitHub Actions；
- 场景：基于旧生产系统的界面和功能，重建新系统；
- 挑战：旧系统有 3248 行的功能描述文档，需要逐字段对照，确保新系统不遗漏任何功能。

这个案例和其他章节不同：前几章学的是"在理想情况下应该怎么做"，这一章看的是"在贴近真实的约束下如何取舍"。两者有差距——而这个差距才是最有价值的部分。

关键决策点一：需求分析——到底用什么技能。

面对"老系统迁移"这个场景，你可能会想：用 Requirements 技能做需求分析。但落到项目实践中，这个决策面临一个选择：用 Requirements 从零分析需求，还是用 Legacy Recon 从老系统还原需求？

- 选择 Requirements 的理由：方法论完整，从 Event Storming 开始逐层推导出需求文档，适合"从零开始"的项目；
- 选择 Legacy Recon 的理由：老系统已经存在，所有功能都已在运行中。与其"重新分析"，不如"逐字段对照"——把老系统已有的功能拆解出来，对照新系统的实现，找出差距。

最终选择了 Legacy Recon。因为老系统有 3248 行的功能描述文档，加上完整的界面快照——这些信息比"重新分析"更准确、更完整。Requirements 需要业务人员参与讨论，而 Legacy Recon 只需要对照已有的实现。

这个决策的核心逻辑：当已有信息比"重新分析"更可靠时，优先使用已有信息。老系统已经上线运行，它的功能描述是对真实需求的精确映射——比任何"分析"都准确。

关键决策点二：架构设计——要不要从头设计。

差距报告出来后，团队面临第二个关键决策：是重新设计架构，还是在现有架构中补充功能？

- 选择重新设计架构的理由：老系统的架构可能有问题，重建时正好可以优化；
- 选择在现有架构中补充的理由：新系统已经上线运行，架构经过验证是稳定的。重新设计会引入不确定性和风险。

最终选择了在现有架构中补充。原因是：差距报告中的 49 项差距，全是"功能遗漏"而非"架构问题"。没有架构性问题，就不需要动架构。

这个决策的核心逻辑：架构设计的价值在于解决问题，而不是为了设计而设计。如果问题不在架构层面，就不要动架构。

关键决策点三：修复任务——要不要用 Workflow。

49 项差距排好优先级后，第三个关键决策：修复任务应该用 Workflow 自动执行，还是用 Coach 手动引导？

- 选择 Workflow 的理由：49 项差距中大部分是"补充遗漏功能"——需求明确、技术方案清晰，符合 Workflow 的适用条件；
- 选择 Coach 的理由：部分修复任务涉及多个模块的联动修改，需要多次确认和调整。

最终混合使用：对"需求明确、单模块修改"的修复任务使用 Workflow 的 auto 模式；对"涉及多个模块、需要确认"的复杂修复任务使用 Coach 手动引导。

以下是虚构复盘示例：一个涉及前后端联动的修复任务，用 Workflow 的 auto 模式执行后，验收发现接口约定不一致。证据只足以说明单模块门禁漏掉了跨模块契约，不能证明工具本身是唯一根因。团队在验收标准中增加"跨模块接口一致性检查"；后续记录的复跑未再次发现同类问题，但这不保证未来不会复发。

关键决策点四：集成验收——修复优先级怎么排。

所有修复任务独立验收通过后，集成验收时发现了两个问题。第四个关键决策：如何安排修复优先级？

- 选择"全部修复再上线"的理由：问题虽小，但都是"不一致"，累积起来会降低系统质量；
- 选择"关键问题修复后上线，非关键问题后续迭代"的理由：两个问题都不影响核心业务流程（学员注册 → 考试 → 发证），可以上线后逐步修复。

最终选择了折中方案：区分"阻塞性"和"非阻塞性"问题。缓存刷新问题是阻塞性的——影响用户看到最新数据，必须上线前修复。日期格式问题是非阻塞性的——不影响功能，计划在下一个迭代中修复。

这个决策的核心逻辑：不是所有问题都需要在同一个版本中修复。区分"必须修"和"可以等"的能力，是经验带来的判断力。

关键决策点五：部署——自动化到什么程度。

第五个关键决策：部署流程应该全自动化，还是半自动化？

- 选择全自动化的理由：Docker + GitHub Actions 已配置好，可以完整 CI/CD；
- 选择半自动化的理由：项目涉及 4 个前端应用 + 1 个后端应用 + 2 个数据库 + 1 个缓存，全自动化可能导致"自动化了但没人敢用"。

最终选择了半自动化：自动构建 + 手动部署。GitHub Actions 自动完成构建和测试，但部署到生产环境需要手动执行一个 deploy.sh 脚本（支持 IP:端口模式 HTTP 访问、域名模式 Caddy 自动 HTTPS）。

这个决策的核心逻辑：自动化的目的是降低风险，不是增加风险。如果全自动化让你觉得"不可控"，那就留一个人工确认的环节。随着项目稳定运行，可以逐步增加自动化程度。

### 37.2 Legacy Recon 的"逐字段对照"方法

执行过程：Legacy Recon（老系统还原）专门处理"老系统 → 新系统"的迁移场景。

- 第一步：建立待办清单。将 7 大业务模块拆分为独立的审计任务；
- 第二步：并行审计。每个模块由独立的子代理审计，逐字段/逐功能对照老系统和新系统的实现。审计方法：前端代码检查界面实现、后端代码检查接口实现、数据库 schema 检查数据模型、整理差距（已有/缺失/部分实现）；
- 第三步：产出差距报告。按"地基优先"排序，高中低全纳入分层。

产出示例（差距报告）：

<!-- code-example:chapter-37-E1 mode:reference -->
> **示例类型：参考。** 参考片段，不保证可独立执行。请按本章上下文、项目版本和真实接口改写，并以实际运行结果验收。
```text
- 高优先级：15 项（影响核心流程）
- 中优先级：23 项（影响用户体验）
- 低优先级：11 项（优化类）
- 第三方依赖标注：5 项（需要外部凭证，延后）
```

一个典型修复任务的执行过程——任务：补充机构端的学员批量导入功能：

- 下发指令（含需求、技术约束、验收标准——使用现有 Excel 解析工具、输入验证规则与单个添加一致、导入结果页面展示成功/失败列表）；
- 编码：AI 自动完成文件上传、Excel 解析、数据验证、批量写入；
- 验收：功能检查（导入正常、字段验证正确）、架构检查（没有修改核心代码、数据模型一致）、安全检查（上传文件类型验证、SQL 注入防护）→ 结论 PASS → 提交。

进度管理（进度账本 job.progress.md）：

<!-- code-example:chapter-37-E2 mode:reference -->
> **示例类型：参考。** 参考片段，不保证可独立执行。请按本章上下文、项目版本和真实接口改写，并以实际运行结果验收。
```markdown
## 老系统功能补齐 — 进度账本
## 已完成
- [x] 机构端·学员批量导入（2026-07-13）
- [x] 机构端·资质变更记录（2026-07-13）
- [x] 管理端·考试员分配（2026-07-14）
- ...
## 进行中
- [ ] 机构端·财务报表导出
## 待办
- [ ] 管理端·数据统计看板
- [ ] 考试员端·评分功能
```

### 37.3 哪些技能用到了、哪些没有用到、为什么

用到的技能：

| 技能 | 使用场景 | 使用程度 |
|------|---------|---------|
| Legacy Recon | 老系统功能审计 | 核心 |
| Inspector | 每个修复任务的验收 | 核心 |
| Workflow | 修复任务的自动化执行 | 核心 |
| Advisor | 技术决策 | 辅助 |
| Coach | 部分复杂功能的引导 | 辅助 |

没有用到的技能及原因：

| 技能 | 为什么没有用到 |
|------|--------------|
| Architect | 不是从头设计，是在现有架构中补充 |
| Orchestrator | 修复任务没有复杂的依赖关系，可以直接按优先级执行 |
| Job | 项目已存在，不需要从零开始 |
| POC | 已有老系统界面参考，不需要原型 |
| Requirements | 需求来自老系统，已经明确 |

### 【复盘】经验的价值：知道什么时候不该用什么技能

关键经验：

1. 老系统迁移的关键是"逐字段对照"：不要依赖文档描述，要逐字段对比老系统和新系统的实际实现；
2. 并行审计提高效率：7 大业务模块并行审计，在本案例的规模下明显快于串行（快 3-4 倍为该案例的演示量级）；
3. 按优先级执行：地基优先（数据模型、核心接口），再用户可见功能，最后优化类；
4. 进度账本保持透明：追加式进度账本让所有人随时了解项目状态。

本案例展示了项目实践中最重要的能力：在多个选项之间做出选择，并为每个选择给出理由。五个关键决策点——需求分析用 Legacy Recon 而不是 Requirements、架构设计在现有架构中补充而不是重新设计、修复任务混合使用 Workflow 和 Coach、集成验收区分阻塞性和非阻塞性问题、部署选择半自动化而不是全自动——每一个决策都不是"理论最优"，而是"在当时的约束条件下最合适"。

这就是经验的价值：知道什么时候该用什么技能，更重要的是，知道什么时候不该用什么技能。

---

## 独立练习

使用虚构或已获授权的脱敏材料，先独立作答，再查看参考。将产物保存为 `chapter-37.md`，写上版本、决定、证据和缺项。

选择一个虚构工单模块，做旧字段→新字段映射，标已实现、部分实现、缺失。设计数据、API、界面三层对照与切换退出条件。

<!-- chapter-artifact-requirement -->
### 本章必交产物：遗留系统迁移路径

以下证据必须出现在本次独立练习的提交物中；正文原有问题用于提供内容，不能替代这些验收项。

- O1: 遗留系统迁移路径按输入输出顺序连接“旧系统接缝”“双轨验证”和“逐步切换”
- O2: 遗留系统迁移路径为三个步骤分别写出负责人、输入、输出和完成标准
- O3: 产物记录一个接缝、并行比较结果、切换条件和回退点

<details>
<summary>查看参考反馈（先独立作答）</summary>

## 参考反馈

字段含含义、单位、空值、权限与兼容规则；API对照状态和错误，界面对照操作和状态。迁移前保护原数据并演练恢复，验证双写或切换一致性。教材规模与效率是教学量级，不是本站客户成果；不可仅用新界面相似判迁移成功。

### 自评与下一步

对照本章目标检查：决定是否明确，依据是否能复现，未知项是否如实记录。参考给出一种判断方式，不是唯一答案；若不同结论能提供同等证据，可请同伴复核。缺少证据的部分记未完成，再回到对应步骤补充。

</details>

## 来源与边界

登记来源只支持本章涉及的外部事实；遗留系统迁移路径、示例数字和练习情境属于课程内部教学设计，必须在实际项目中重新验证。

- [绞杀榕式遗留系统现代化](https://martinfowler.com/bliki/StranglerFigApplication.html) — Martin Fowler, 2026-09-17. 遗留系统可以通过识别接缝、隔离小组件并逐步替换来降低一次性重写风险。
