记得2018年接手那个医院挂号系统的时候,git log显示第一行提交是凌晨3点47分,提交信息就两个字"ok"。当时主数据库表只有两张,一张用户一张号源,所有逻辑都挤在一个叫ZhangSan的类里——据说写这个的人真的叫张三。我花了整整两周才看明白那些缩进不一的代码,却意外地觉得顺畅,因为角落里藏着个2000行的函数,注释写着"别动,会炸"。后来我们重构了它,分拆成二十个文件,每个文件都干干净净,测试覆盖率刷到90%。可去年再打开这个项目,我认不出自己写的任何一个函数了,因为需求迭代让每个文件都塞回了过去的样子。
那时候我明白了一个恶心的道理:代码的初生状态是它最好的状态。就像新房刚装修好的那种透亮,但住进去以后,你总得往墙上钉钉子、挂衣服、堆纸箱。每加一个if判断,每修一个edge case,都在给这栋楼添砖加瓦。对比极其残酷——我刚写的模块,命名清晰,单一职责,单元测试里每个mock都干净利落;三个月以后,同一个模块多了六个boolean参数,因为产品经理说"这个按钮在特殊情况下要变灰",而"特殊情况"由四个不同服务分别触发。我试过用DDD、用贫血模型、用事件风暴,所有方法论都只能延缓腐烂的速度,没法阻止它。
真正让我产生颠覆想法的是一次误删数据库的经历。当时要改一个字段长度,手一抖把整张表drop了。恢复备份花了四个小时,那四个小时里我盯着错误日志,突然意识到:这套系统里所有代码、所有架构图、所有最佳实践,本质上都是一堆临时措施的组合。我们追求的高内聚低耦合,其实是人类对混乱的病态抵抗。宇宙的本质是熵增,代码也是。你写一百行好代码,产品经理就能产生两百个新需求;你重构一次,就能换来下一个月的平静,但下个月依然会烂掉。所以软件开发的真正产物从来不是软件,而是团队与腐烂赛跑过程中积累下来的默契——什么时候该妥协,什么时候该推倒重来,这种直觉没法写进规范。
现在我写代码,不再执着于什么完美设计了。我给自己定了条规矩:每个模块留一个丑的地方,作为"腐烂标记"。比如某个函数故意不写注释,或者保留一个没用的参数,这样下次看到的人知道这里已经够烂了,别再增加负担。这听起来像个笑话,但真的有效——当我发现所有代码都看似完美时,反而更危险,因为大家会像对待圣旨一样不敢动它,而腐烂会在看不见的地方悄悄发生。好的软件工程不是把代码写得有多漂亮,而是清楚地知道哪块已经死了,然后含着泪在它旁边建新的。就像园艺师,不是让所有植物都开花,而是知道那棵老树已经空了,索性把根砍掉。这场对抗熵增的仗,我认输,但认输之后反而轻松了,因为接受了腐烂,你才能真正理解什么是维护。