安全修改现有系统
已完成引入修改时保留当前约定。考虑旧客户端、已有数据和部署顺序。
检验理解在同一次发布中重命名数据库列并更新应用,仍可能出现什么问题?完成练习
你将学到什么
- 识别局部代码修改可能影响的约定。
- 解释分阶段的先扩展、后收缩变更。
- 区分代码回滚与数据恢复。
识别修改周围的约定
现有软件包含调用方、已存储数据、定时任务和运维流程。有些依赖无法从要编辑的文件中看出。智能体可能生成局部正确的修改,却破坏其中一项约定。
实现前,识别受影响数据的读取方和写入方。检查路由、后台任务、报表和外部集成。确认其他团队或旧客户端版本是否依赖当前行为。
要求智能体为这些依赖关系提供证据。搜索结果是有用的起点,但动态调用和外部使用方可能需要负责人确认。
让当前行为可观察
对于文档不足的模块,为必须保持稳定的行为添加针对性检查。这些检查描述当前约定,但不能证明现有行为全部合理。
如果当前行为与要求冲突,应记录冲突。不要仅因为某个测试记录了安全缺陷,就保留缺陷。取得必要决定,以区分预期行为与缺陷。
使用贴近实际且不含敏感信息的测试夹具。如果可能出现旧数据结构或不完整记录,就将它们纳入。只用新建数据测试新的数据模式,可能掩盖迁移问题。
审查版本之间的过渡
考虑一个虚构的重命名:将 customer_name 改为 display_name。立即重命名可能导致部署期间旧应用实例出错。在同一个 pull request 中修改两个文件,并不意味着部署具有原子性。
分阶段处理可以保留兼容性:
- 添加新字段,先不删除旧字段。
- 定义新写入如何保持所需值一致。
- 使用可重新启动的流程回填现有记录。
- 验证完整性和读取方行为。
- 将读取方迁移到新字段。
- 只有所有使用方都不再依赖旧字段后,才删除旧字段。
具体方法取决于数据库和写入模式。如果其中一次写入失败,双写可能造成不一致。可能需要数据库事务,或其他明确的同步方法。检查系统保证之前,不要直接套用这个示例。
Martin Fowler 将这种一般过渡方式称为并行变更,也称先扩展、后收缩。核心是在移除前完成兼容过渡。
单独规划恢复,不要与回滚混为一谈
代码回滚恢复的是早期应用版本,不会自动撤销数据迁移。旧版本可能不理解新数据。破坏性迁移可能删除代码回滚无法恢复的信息。
明确每一步的恢复操作。可重新启动的回填可能可以安全继续。错误转换可能需要根据保留的源数据修正。破坏性操作可能需要经过验证的恢复流程。
询问谁负责恢复决定,以及恢复可能需要多久。不要把“我们有备份”当作恢复满足服务要求的证据。
让修改便于审查
将无关清理与功能修改分开。在 pull request 中提供兼容性计划、验证结果和移除条件。标明从哪一步开始,回滚需要额外工作。
智能体可以帮助检查使用方并准备迁移代码,但仍需由负责人接受过渡和恢复计划。最终设计只是安全变更的一部分。
完成练习
选择一个小型字段或 API 修改。列出所有读取方和写入方,包括后台任务。描述先做加法的第一步、过渡检查和移除条件。识别哪一步可能导致无法回滚。
下载工作表(Markdown)取消勾选将删除此浏览器保存的全部进度。
进度保存在此浏览器中。无需账户,不追踪使用情况。