一个运行多年的系统,可能技术栈陈旧,却能稳定处理业务;也可能页面看起来正常,背后全靠人工补数和少数人的记忆维持。仅凭代码年龄,很难决定该不该改造。
讨论改造方案前,先约定要解决的问题:是故障恢复太慢、需求交付受阻,还是业务规则已经改变?如果各方说的是不同问题,重写和采购方案就无法放在一起比较。
先把现状变成可核对的证据
用一个有代表性的业务周期整理三类记录:
- 运行损失:哪些事故影响了订单、履约或结算,持续多久,人工补救了什么。区分实际损失与尚未发生的风险。
- 变更成本:挑几项已经完成的同类需求,拆出开发、等待、回归和上线的时间,查清延误来自代码、流程还是外部依赖。
- 维护条件:谁能修复关键模块,依赖是否仍可维护,备份是否做过恢复验证,业务规则是否有其他人能解释。
业务负责人确认影响,技术负责人确认成因和约束。有些问题只需要统一流程,有些风险必须马上隔离。不要把它们全部归入一个“系统升级”项目。
四条路径,各自解决不同的问题
继续维护:适合变化少、风险可控的部分
如果核心流程稳定,变更成本可以接受,维护人员和恢复手段都在,继续维护可以是合理选择。此时投入应聚焦备份恢复、关键监控、权限检查和必要文档。
同时写下重新评估的触发条件,例如关键依赖失去维护支持、同类变更成本持续上升,或现有容量无法承接已经确定的业务计划。这样,维护有明确边界,不会自动变成无限期拖延。
外围封装:适合先隔离变化
核心账务暂时不宜动,但新渠道需要查询能力时,可以先增加接口层;高频变化的通知、展示或活动规则,也可逐步移到外围。
每次封装都要明确哪个系统拥有最终数据、失败怎样重试、异常由谁处理。外围系统原则上通过约定接口访问核心能力,避免多个应用直接写同一组表。接口层若不断复制旧业务逻辑,后续迁移会更难,应定期删除已经失去作用的过渡代码。
模块替换:适合问题集中、边界能划清的部分
可以先替换一个边界清楚的模块,再逐步缩小旧系统职责。替换既可能采用现成产品,也可能自主建设。前者要验证实际流程和数据导出能力,后者要评估长期维护负担。
先选能够独立验收、依赖可控的范围。表面上独立的订单页面,底层可能同时承担库存和结算规则;这些关系没查清,就还不具备独立替换条件。
全面重写:需要足够强的理由和迁移能力
当业务模型已根本改变,或者局部改造会反复触碰同一组无法隔离的核心约束,才值得认真评估整体重建。
重写前至少要说明:哪些问题局部治理无法解决,哪些历史功能可以退休,新旧数据如何核对,切换失败怎样恢复。需求不清、业务负责人缺席、恢复方案未验证,都应成为暂缓启动的理由。团队写新代码的能力不能代替这些条件。
比较的是完整成本
把候选方案放在同一个计划周期内比较,周期要匹配业务变化速度。成本至少包括建设、双系统运行、迁移核对、培训、旧系统维护和最终下线。现成产品还应考虑接口限制、后续配置维护及退出时的数据交接。
继续使用旧系统也有成本,但需要避免夸大:已经发生的维护人时可以列实数,未来故障和机会损失只能用区间或情景估计,并说明依据。对不确定的收益,不要用一个精确的回报率掩盖判断。
若两个方案收益相近,优先考虑能分段验证、失败影响更小的路径。对于必须处理的安全或数据完整性问题,则先降低风险,再安排长期改造。
一个情境示例:从库存查询开始
假设一家企业的旧系统结算稳定,但库存查询延迟影响销售承诺。第一步应确认延迟来自同步任务、查询性能,还是业务没有及时入库。
如果问题来自查询负载,可以试做只读查询服务;如果来自入库流程,应先调整流程。如果确实要替换库存模块,则先约定库存事件和账面数量以哪里为准,再选一个有限范围验证。
试点不能只检查页面是否变快。还要核对库存变动是否完整、重复消息会不会重复扣减,以及异常订单如何追踪。只有这些问题有答案,才有依据扩大切换范围。
切换前,把退路走一遍
并行运行应尽量采用只读对比或影子计算。必须双写时,需专门处理失败补偿、重复写入和冲突,不能把“双写”当作天然安全的过渡方式。
代码回滚也不等于业务已经恢复。新系统处理过的订单、修改过的数据,可能无法直接交回旧系统。演练要覆盖切换后新增的数据,确认恢复目标、核对方式、操作权限和业务通知负责人。
在切换前约定停止条件:关键数据无法对平、核心异常无人接管、恢复超过可接受时长,就停止扩大流量,按预案处理。验收除了功能可用,还应包含约定的业务改善、维护负担和稳定运行证据。
最后为旧系统安排明确的退役动作:关闭写入、保留必要查询和归档、撤销无用接口及权限。只有旧职责真正退出,改造的复杂度和成本才可能降下来。
