最好的代码是那行你从未写下的代码。这个想法听起来像是偷懒的借口,直到你花了几年时间去维护别人当年的“热情”。写软件感觉像是在建筑,但它的行为更像是在园艺。任其生长,花园无论你愿不愿意都会生长。代码也是如此。真正的手艺在于懂得何时停止播种。

你的代码是一种负债

你提交的每一行代码都会产生一系列持续的义务。你会在深夜处理突发故障时再次阅读它。当你的框架发布一个改变字符串处理方式的小版本更新时,你需要测试它。当生产环境的日志毫无意义时,你需要调试它。你需要向刚入职一周的队友解释它,或者在十二个月后当上下文已经烟消云散时,向你自己解释它。

这并不是在主张晦涩难懂。这是几何学。漏洞需要空间来隐藏。你的“表面积”越小,故障能钻进去的地方就越少。一个拥有 80 行代码和 6 层嵌套条件的函数不仅更难阅读,而且在统计学上更有可能给你带来“惊喜”。克制并非不努力。它是一种认知:未写的代码缺陷数为零。

当聪明变成一种税收

考虑这样一个任务:根据一些业务规则计算订单总额:应用折扣、检查应税项目、跳过任何标记为已删除的项目。一位开发者写了一个单一的表达式。它通过复杂的过滤器链对列表进行流处理,调用辅助库,使用柯里化(curried)的归约器(reducer)折叠结果,最后返回总和。它很紧凑,在学术意义上甚至可能很优雅。但要读懂它,你必须在同一时刻理解辅助库的隐式类型转换、流内部的操作顺序以及业务逻辑。你无法在中间设置断点,也无法在不破坏链式调用逻辑的情况下插入一条日志语句。这段代码在页面上很短,在脑海中却很长。

另一位开发者写了一个基础循环。她声明一个累加变量,遍历项目,并使用简单的 if 语句来决定是否适用税费。代码块在垂直方向上更长,但意图显而易见。你可以从上到下阅读,而不需要在脑海中同时维持五个抽象概念。你可以在调试器中单步执行。你可以在第四行添加日志,而无需重构整个表达式。

聪明代码在 Pull Request 中看起来很高级,但也就维持十分钟。简单的代码看起来很枯燥,而当你凌晨两点在排查故障时,枯燥正是你所需要的。你的目标是清晰,而不是展示智力。

系统需要结构,而非英雄

这一原则可以扩展到架构层面。一个“聪明”的系统可能依赖于手写的共识逻辑、定制的编排脚本,以及只有一名工程师真正理解的、未记录的缓存捷径。这样的系统无法独立运行;它依赖于维持其运转的人不断迸发的才华。当那个人休假或换了工作,系统就开始摇摇欲坠。

设计良好的系统则依赖于结构和约束。它们使用拒绝错误数据的数据库 Schema,定义边界的 API 合约,在部署前捕获类别错误的类型系统,以及使预期路径显而易见的模块分离。它们不需要英雄主义来保持稳定。它们的设计初衷就是为了在与疲惫的人类接触时生存——而疲惫的人类是唯一会在生产环境中操作软件的人。

AI 放大问题

人工智能编程助手让这一教训变得更加紧迫。这些工具生成文本的速度极快。你给它们一个简单的问题,它们往往会返回一个庞大且复杂的解决方案:导入了你内部已有封装的工具类,处理了你的业务领域并不存在的边缘情况,并使用了你两年前就已迁移掉的框架版本的惯用法。AI 关注的是眼前任务,而你必须关注整个系统。

如果你不管理长期成本而全盘接受每一个建议,代码生成就会导致“通胀”。你的代码库会充斥着看起来合理、能通过编译、能通过测试,但却没人真正理解的代码。危险并不在于显眼的语法错误,那些错误在评审时就会被发现。危险在于代码库逐渐变得臃肿,每一个单独的文件看起来都还算合理,但整体复杂度却超出了任何单个人类大脑的承载极限。这就是工程效能消亡的方式:不是伴随着一声巨响,而是在于那些无人敢删的冗余代码在悄无声息地堆积,因为人们害怕触碰那些自己无法完全掌握的东西。

删除也是一种设计技能

优秀的工程师并不通过比别人打字更快来证明自己。他们通过选择简洁,通过选择“删除”而非“堆积”来取胜。删除代码需要对其有深刻的理解。你必须追踪数据流,确认某个功能没有隐藏的调用者,并验证业务逻辑是否已经不再需要。删除比增加更难,因为它要求极高的确定性。

团队通常会为交付的功能和提交海量 Pull Request 的高产开发者欢呼。但很少有团队会为那位删除了四千行冗余逻辑、让系统运行更快且更易于理解的工程师喝彩。然而,这种“负增长”的代码行数,往往是对组织未来更大的贡献。

昂贵的部分

现在的代码很廉价。任何人都能在几秒钟内生成数页代码。昂贵的资源是清晰度。保持系统的可理解性需要时间、判断力和克制。真正的工程实践发生在“编辑”阶段,而非“草拟”阶段。

少写代码。多删代码。设计要简洁。