架构上的决定,半年后没人记得
一、为什么特意留的那一步会被当成多余
举个例子:一家做区域冷链配送的公司,八十来个人,技术团队六个。四年前上线下单系统时,工程师在提交订单之前多加了一步:先去仓库那边把货占住,再去算运费。
这个顺序不能反。这么定有原因:仓库那套占库存要两秒多,运费算法快。反过来的话,运费算完了才发现没货,客人已经付了钱。
一年前,一个新人接手这段代码,看这一步不顺眼。占库存和算运费是两个外部调用,为什么要排队等,一起发出去不是更快。他改成并行,测试也过了。
改完后的第一次大促,超卖了一百多单。查到最后,是那两步的顺序被换掉了。
二、丢掉的是为什么,不是怎么做
那一步的代码还在,函数名也还叫占库存。真正丢掉的只有一样东西:当初为什么必须先做它。
怎么做写在代码里,为什么写在做决定的人脑子里。人还在,两份都在;人一走,第二份就没了。
这不是粗心。做决定的那天,没人觉得需要写下来,因为大家都觉得这事大家都知道。
那家公司的复盘里写了一句:这次改动不是糊涂蛋干的,是一个聪明的新人,对着一份没写理由的代码,做出了合理的判断。
三、注释还在,为什么还算丢了
有人会反驳:代码里不是有注释吗。那家公司这段代码确实有一行注释,写的是「先占库存」。
注释说的是这一行在做什么,不是当初为什么非这样做不可。前者机器也能看出来,后者只有人知道。
更容易出事的是另一种情况:注释写了原因,代码却改了三次,注释还停在第一次。新人照着旧注释去理解,理解错的是整块。
他们后来把那一行换成一句完整的话:仓库占库存要两秒多,反过来会先算完运费再发现没货,导致超卖。原因带着后果,才拦得住下一个人。
四、哪些决定值得写,哪些不必
不必什么都写。变量怎么命名、循环怎么写,看了代码就知道,写下来只是给自己加活。
要写的有三类。第一类是选了这条就放弃那条的,比如用消息队列而不是直接调用;第二类是看着多余、其实有原因的,比如上面那个顺序;第三类是花了钱或者签了合同的,比如为什么必须放在某一家云上。
判断这三类有一个简单问法:如果三年后有人问「这里为什么这样」,现在在场的人能不能给出同一个答案。给不出,就该写。
那家公司最后圈出来要写的只有十一条,全是四年前那批人做的决定。一个下午就写完了。
五、一条决定要写哪几样才算写全
格式不必复杂,但要凑齐五样:当时的问题是什么、比过哪几个方案、选了哪个、为什么选它、代价是什么。
第五样最容易被省掉。任何选择都有不划算的地方,不写下来,下一个人只会看到好处,觉得当初怎么不全都照这个做。
还要带一个日期。规模、成本、排期这些东西会随时间变,一条两年前的理由,今天可能已经不成立。
那家公司给每条多加了一行「什么时候这条作废」。写的是作废条件,不是日期。比如仓库那边哪天改成秒回,第一条就可以不守了。
六、写在哪里,文档、工单、代码里还是群里
位置比格式重要。写在共享文档里,能搜到但没人看;写在工单里,工单一关就沉下去;写在群聊里,三天后翻不着。
一个可行的分工是:结论跟着代码走,过程留在文档里。改这段代码的人第一眼要看到理由,所以理由必须离得近。
具体做法可以很土。在代码仓库根目录放一个目录,一条决定一个文件,文件名带上编号和日期。土,但新人第一天就能翻到。
那家公司最后放进了代码仓库,和代码一起改、一起提交、一起被审。想改那一步,就得先改那一页。
七、谁来写、谁签字、什么时候不许再改
写的人就是做决定的人,别交给别人补。别人补出来的是结果,不是理由。
签字的人要具体到岗位。客户这一类东西归谁管,那一条就归谁签字。没有签字人,写下来也没人守。
已经定过的决定不许就地改。要变,就新写一条,把旧的标成被取代。原因很简单:留着旧的那条,后来的人才知道中间为什么绕了一圈。
那家公司出过一次反例。有人直接改了旧文件里的结论,两个月后新的那条和旧的混在一起,没人说得清哪条算数。
八、换供应商换框架,旧决定要不要跟着作废
换掉一家供应商,跟着是一批旧理由失效。这时候要做的不是删,是逐条重看:当初为什么选它,这个理由今天还成不成立。
常见的坏结果有两种。一种是旧决定没人管,新系统照着一套早就没道理的做法跑;另一种是一刀全删,把当初真正有用的那条也删了。
判断标准很朴素:这条理由里提到的那个东西还在不在。提到那家供应商接口慢,供应商换了,这条就该重看;提到超卖要赔钱,这一条永远作不了废。
那家公司换仓库服务商的时候,十一条里作废两条、改写三条,剩下六条原样留着。
九、新人接手读什么,工具读的是不是同一份
新人接手通常有一份交接说明,讲系统有哪几块、每块干什么。这类内容讲的是是什么,不讲为什么不能改。
现在多了第三种接手人:AI 编码工具。它读代码、读注释、读你递过去的文档,读不到理由,就会按通用的做法去改。
通用做法本身没错。并行调用确实比排队等快,问题在于这一步慢是有意的,而工具不知道。
所以那份东西得能被读到。写在人脑子里、写在某个群里、写在一张没人维护的表上,等于没写。
十、工具会不会把老决定改得更勤
会。改代码这件事的成本降了很多,以前要排两周的活,现在一个下午能出好几版。改得勤,撞上的旧决定就多。
今年这一块的讨论明显变多,方向也一致:把架构上的决定写成一条条能查到的条目,在工具动手之前,先把相关的几条摆到它面前。
有一个区分值得记住。跟眼前这次改动「沾边」的决定,不等于「适用于」这次改动的决定;就算适用,也不一定都能用机器去卡。能卡的写成检查,卡不了的写成说明。
那家公司没上任何新工具,只做了一件事:把十一条放进代码仓库,又在给工具的说明里加了一句,改之前先读这个目录。
十一、写下来之后,怎么保证真的被用上
只写不查,半年就废了。两个动作最简单:改代码时要人回答一句「这次动没动到那十一条里的某一条」;上线前抽查一次,看新改的地方有没有对应说明。
别指望人自觉。要在流程里设一道看得见的关卡,比如代码合并前那一屏,把这份目录列成必看项。
也别走到另一个极端,把每一条都变成机器检查。真正能被机器卡住的只有少数几条,剩下的只能靠人读。
那家公司的做法是把这十一条贴在大促前的检查清单末尾,检查时逐条问一句:这次改动有没有碰到这里写的东西。
十二、第一次做这件事,从哪一条开始补
别从最重要的那条开始,从最近被人改错过的那条开始。这种条目有现成的教训,写起来不用猜,别人也认。
第二条补那种新人一定会问为什么的。比如为什么这里要多存一份、为什么要晚十分钟再算、为什么这个字段不许改。
一次只写一页,一页不超过两百字。写长了没人读,也没人肯跟着更新。
那家公司是从超卖那一条开始补的,写完一共花了四十分钟。第二周就有人拿着这一页来问:那另外几处顺序,是不是也有原因。
十三、多久回头对一次,怎么发现决定已经过期
一年一次就够。最好放在换供应商、换大版本或者团队换人那几件事前后,那时候本来就要把系统重看一遍。
对的方法不是逐条读,是问三个问题:这条理由里提到的东西还在吗;这一年有没有人绕过它;绕过的结果是出事还是没事。
第三个问题最有用。如果一年里有人绕开三次都没出事,这条大概已经过期,或者当初就把话说重了。
那家公司第一次回头核对,发现十一条里有两条被绕开过。一条确实过期,另一条是当初写的时候把话说大了。
十四、老板只要问三句话
第一句:我们系统里那些看着多余其实有原因的地方,有没有一份写下来的清单。没有,就先补三条。
第二句:这份清单放在哪,改代码的人第一眼看不看得到。看不见,等于没写。
第三句:过去一年有没有人绕过清单上的某一条,绕了之后出事没有。
那家公司最后留下的不是一本架构手册,是代码仓库里那十一页。每次有人想省掉一步,就先被问到这一页。
本文作者:Aryee 发布时间:2026-10-27 06:19
本文出处:ARYEE.cn 固定链接:https://www.aryee.cn/archives/nobody-remembers-why-designed.html
转载或引用请连这一行一起带走;文中的代码与结论按当时环境成立,组件升级后请以官方文档为准。