代码能跑就不改,这句话在公司茶水间里被提起的频率,差不多和“在我机器上是好的”一样高。听上去这像一条保命准则,尤其是面对那种已经上线五年、原开发人员早就离职,文档只剩下一段README写着TODO的老旧系统。谁动手改动,谁就要承担对应的风险。于是所有人都绕开这块代码,新增需求只能一层一层叠加if判断,排查bug优先选择重启服务,数据对不上就单独写脚本手动补齐。这套操作模式能维持很长一段时间,久到团队里没人说得清这套系统当初到底是怎么正常运转起来的。

但“能跑”这个说法本身就很模糊。在测试环境正常运行算能跑,生产环境峰值压力下不出问题也算;跑在Java8环境没问题,升级到Java17之后能不能正常工作没人清楚;在原来那台物理服务器上能启动,迁移上云之后说不定直接无法启动。大家口中的能跑,大多只是:在当前这套没有改动过的环境,按照现有人员的操作习惯,处理当前量级的数据,暂时没有出现故障。它只是一张随时会失效的临时通行证,并不是永久稳定的保障。
有些场景下选择不去改动代码,确实是理性判断。比如一款已经出货几十万台的嵌入式设备,固件里面那段汇编代码刚好能节省几毫秒耗时,如果强行用C语言重写,最后造成功耗上升,引发客户退货,这就算不上技术优化,只是无端制造麻烦。还有银行核心系统,已经稳定运行十几年,每一行代码背后,都关联着过往的监管核查、各个分行独有的业务流程,还有很多没人记得来由的补丁。一旦改动其中一块,很容易触发连锁故障,修复需要付出的成本远远高于改动带来的收益。这种情况不去修改代码,并不是偷懒,是权衡利弊之后做出的选择。
麻烦就在于,很多团队慢慢把这种权衡变成了条件反射。只要有人抛出一句“能跑”,讨论就直接终止。没人深究代码为什么可以正常运行,也没人评估下次还能不能继续稳定工作。代码里硬编码的IP地址、写死的文件路径、重复复制多遍的业务逻辑,还有为绕过某个bug加上的sleep 5000延时,全部被打包归到“历史原因”这个笼统借口下。历史原因就像一个筐,所有说不清的问题都能往里塞。久而久之,新来的工程师看不懂代码,也不敢提问,一问得到的回复基本都是“你先慢慢熟悉”。等他花半年摸熟之后,也学会了这套说辞,跟着说能跑就不要改动。
技术债这个词现在被用得泛滥,不过它的核心含义并不复杂:当下为了省事做出的技术取舍,会抬高后续某一项工作的成本。要注意,只是部分工作,不是所有业务。一部分技术债属于良性,比如初创团队为快速做出演示原型,用粗糙的方式搭建版本,先拿到融资。这类债务后续有机会偿还,也值得去处理。还有一类属于恶性技术债,像明文把用户密码写入日志、依靠数据库默认隔离级别控制并发、用while true循环写重试逻辑,这类问题不会自行好转,只会在某个凌晨三点,以很难处理的形式爆发故障。
真正棘手的地方,是技术债不会体现在财务报表上。它体现在每次需求评审,后端开发告知这个改动会影响支付模块,需要预留两周工期;体现在扩容的时候,运维发现服务标注无状态,但会话信息全部保存在内存;体现在安全扫描输出二十多个CVE漏洞,却没人敢升级依赖包,升级就要改动代码,改完还有服务异常的风险。这些开销不会出现在当日报表,但是会体现在后续项目排期、突发故障,甚至员工离职潮里面。
“能跑就不改”这个想法能被广泛接受,还有个不容易察觉的原因:它把组织层面的问题包装成了技术层面的真理。一套系统没人敢碰,未必是代码本身完全不能改动,而是掌握修改方法的人已经离职,或者还在岗但不愿意分享经验。相关知识没有沉淀成文档、测试用例和监控方案,全部只存在少数几个人脑子里。这时“不改动”就变成一种话语权,也是一种自我保护。谁提出重构,就等同于挑战系统稳定性,后续任何微小异常都要由他负责。一旦形成这种氛围,技术债就不再只是代码层面的问题,变成了人的问题。
判断代码该不该修改,不需要复杂高深的理论,只需要问几个简单实际的问题:这套系统后续还要维护多久?如果半年内就要下线,大规模改动确实没有必要。改动一旦出错,最坏的后果是什么?只是页面短暂卡顿,还是账务计算出错,或是影响病患取药?现在不动,三个月之后再修改,成本会翻几倍?有没有对应的测试用例兜底?缺少测试的话,能不能先补齐测试再动手?这些问题没有统一标准答案,但提出这些疑问,至少能把讨论从“能跑”这种模糊感受,转移到实实在在的得失评估。
代码能够正常运行只是底线,不是最终目标。一辆车子可以点火启动,不代表不用更换机油、检查刹车、查看轮胎鼓包。你可以选择不去维修,但要清楚自己在承担什么样的风险。最忌讳的,是把暂时没发生故障当成完全没有问题,把不敢改动说成没必要改动,一群人坐在刹车片已经磨损严重的车上,互相安慰车子现在跑起来还算平稳。



