做技术这么多年,我越来越觉得写代码这件事其实分成两种:一种是把功能写出来,另一种是让代码能长期活下去。很多人只擅长第一种。所以当一个运行了三年的老系统交到你手上时,你面对的往往是一堆“能跑但没人敢动”的代码。今天这篇,是“写给高级程序员的设计原则”系列的第五篇,我想认真聊聊设计原则里最容易被忽视、但也最决定系统长期命运的一个维度:发展。
这里说的“发展”,不是指业务增长或者个人晋升,而是指系统本身在持续变化中的生存能力。一个高级程序员和一个普通开发者的分水岭,往往也在这里:普通开发者在思考“今天怎么把需求上线”,高级程序员在思考“这个设计在半年后、三年后还能不能平稳地往前走”。想明白这件事,你的代码就不只是功能的载体,而是一个有生命周期的资产。
1. 为什么说“发展”是高级程序员绕不开的设计维度
1.1 代码资产的本质:从“写出来”到“长出来”
我维护过一个订单系统,上线五年,里面的状态机前后改了十七次。最初只有“待支付、已支付、已发货、已完成”四个状态,后来硬生生加出“退款中、退款失败、部分退款、售后中、冻结、超时关闭”等一堆分支。每一次加状态,所有人都觉得“就加一个枚举值,没事”。但到第十次的时候,每个状态流转函数里都塞满了条件判断,改一处要跑三遍全链路回归,因为谁也不知道这条状态路径会不会被某个隐藏的角落所影响。
这就是我想说的第一件事:代码不是“写”出来的,而是“长”出来的。你第一天写的设计只是种子,后面每一行代码、每一次需求变更,都是在给这棵树施肥或者浇毒药。好的开发者在写第一版的时候就会去想:这棵树以后会长成什么形状?哪些枝干应该粗壮可以承载新功能,哪些地方应该预留嫁接的位置?
软件系统有一个天然的趋势,就是走向混乱。用热力学的词来说,叫“熵增”。没有外力干预,系统的复杂度只会不断累积:这里加个if,那里补个参数,这里塞个枚举,那里复制一段逻辑。而设计原则存在的意义,本质上就是对抗这种熵增。其中“发展”这条原则,专门负责回答一个问题:系统在经历长期变化后,是变得更清晰,还是变得更混乱?
判断一个系统的设计好不好,不是看它今天实现了多少功能、用了多新的技术、压测性能多漂亮,而是看未来每次改需求时的平均成本。如果你把需求改动看成一次“编辑”,那好的设计是让编辑成本随系统规模缓慢上升,差的设计则是让编辑成本指数级飙升。这个区别,前半年看不出来,一年后开始有感觉,三年后就是天壤之别。
1.2 高级设计思维与初级设计思维的分水岭
初级设计思维的核心特征是“就事论事”。用户说要一个优惠计算功能,那就写一个优惠计算模块;用户说规则要变,那就改这里的if-else。整个过程非常线性,也非常感性——因为每一行代码都在响应当下最具体的需求。问题在于,大多数系统都不只活一个版本,它要活很多年,经过很多人的手。
我有一次在一个老项目里看到一个神器:一个两万多行的工具类,里面全是优惠规则判断。最初写的时候,所有规则都堆在同一个方法里,用if-else串联。开发了两周上线,确实很快。后来规则越来越多,从最开始的3条涨到47条,每次加规则都像在雷区里跳舞。为什么?因为这个设计没有给“发展”留下任何空间——所有规则耦合在一起,牵一发而动全身。
高级设计思维则完全不同。它的核心是两个问题:第一,这个需求将来会怎么变?第二,这次改动对系统的整体结构是加分还是减分?注意,不是让你去预测需求,而是做一个合理的判断:哪些部分将来大概率会变,哪些部分相对稳定。比如优惠计算的规则本身一定是频繁变化的,那就要把“规则”和“计算框架”分离;而订单的基础字段、金额单位这些,变化概率低,就值得用强约束去保证稳定。
我经常跟团队里的同学说一句话:如果你只盯着眼前的需求写代码,你永远是需求的奴隶;如果你能在实现需求的同时,让系统的结构变得更好一点,你才是系统的设计师。这个差距不需要五年工作经验才能拉开,只要思维转换,三个月就能体现出来。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 面向发展设计技术底盘:契约、版本与兼容性的三重门
2.1 接口契约:改代码容易,改契约很难
如果说代码是系统的血肉,那接口契约就是系统的骨骼。骨头定了型,肌肉怎么长都有个边界。很多系统死在半路,不是死于性能,而是死于契约的随意变更。
我印象很深的一个
