你花3小时重构的代码,第二周就被删了
上周五下午,我花了整整3个小时重构一段支付回调的处理逻辑。
原来的代码能跑,但丑。if-else套了四层,变量名像是猫趴在键盘上打出来的,注释约等于没有——唯一一行注释写的是// TODO: fix later,时间戳显示是两年前。作为一个有追求的程序员,我忍不了。我抽了三个方法,引入了策略模式,加了完整的错误处理链,写了详细的注释,最后还跑了一遍Prettier确保缩进完美对齐。提交的那一刻,我看着自己的代码,觉得它简直像一首十四行诗——押韵、工整、赏心悦目。我甚至截了个图发到朋友圈,配文”优雅永不过时”。
然后周一站会,产品经理说:”那个支付渠道的合作谈崩了,相关代码全删。”
我的3小时精雕细琢,变成了git log里的一行墓志铭。
你可能觉得这是个极端案例。但回想一下你自己的git log——有多少次,你花了大量时间打磨一段代码,结果它要么被重写了,要么被废弃了,要么从上线到下线,总共被打开过的次数一只手数得过来?
程序员有一种病,叫”代码洁癖”。 症状是看到不够优雅的代码就浑身难受,不重构就睡不着觉,严重时会在梦里给同事的代码做code review。这病不致命,但很烧时间——而且和脱发一样,越资深越严重。
好代码不等于干净代码
大多数程序员脑子里有一个根深蒂固的等式:好代码 = 干净代码。所以不管写什么,都要写到最好。一次性的数据迁移脚本?得加异常处理。临时的debug工具?得写单元测试。给运营做的一次性数据导出?得用设计模式——恨不得导个Excel都搞个AbstractExcelExportStrategyFactoryBean。
这个等式的问题在于——它忽略了一个关键变量:这段代码要活多久。
一次性脚本写得像艺术品,是浪费。核心业务逻辑写得像草稿,是犯罪。这两种情况需要完全不同的投入,但”代码洁癖患者”会一视同仁地把它们都打磨到闪闪发光。
不同生命周期的代码,应该有不同的投入预算。 这不是偷懒,这是工程判断力。
你打磨的代码,有一半不会再被打开
Google内部做过一项代码库分析,结论相当扎心:超过50%的代码,在写完后的6个月内不会被任何人再次修改。
换句话说,你花在”让它更完美”上的时间,有一半的概率是在打磨一个不会再被打开的文件。就好比你花了一个周末给出租屋的卫生间贴了意大利进口瓷砖——下个月你就搬走了。
这不是说代码质量不重要。这是说,代码质量应该跟代码的生命周期匹配,而不是跟你的审美匹配。
你的审美告诉你”这段代码不够优雅”,但工程判断应该先问:”这段代码还会活多久?还有多少人会碰它?”
装修出租屋和装修自住房
用装修来打比方,你一下就明白了。
出租屋的装修标准是什么?能住就行。墙刷白、家具齐、水电通。你不会在出租屋里装中央空调和全屋智能,不是因为租客不配,而是投入产出比不划算——你投了10万装修,租金多收不了2000,三年后租客搬走,你的智能马桶可能已经被用坏了。
自住房就不一样了。你打算住20年,那中央空调、地暖、好的隔音——这些投入分摊到20年里,每一分钱都值。
代码也是一样的道理。问题在于,很多程序员分不清自己写的是”出租屋”还是”自住房”。或者更准确地说,他们把所有代码都当成自住房来装修。
我见过有人给一个两周后就要下线的活动页面写了完整的状态管理方案,用了Redux全家桶。我也见过有人给一个核心支付模块的代码review提了一句”looks good”就过了——因为他已经把时间全花在了前面那个活动页面的架构设计上。
时间和精力是有限的。花在错误的地方,就一定会在正确的地方缺席。

代码投入度决策矩阵
说了这么多,给你一个实操工具——代码投入度决策矩阵。两个维度:变更频率(高/低)和生命周期(长/短)。

第一象限:高变更频率 + 长生命周期 = 核心业务代码
这就是你的”自住房”。用户登录、订单处理、支付流程——这些代码你和你的同事要跟它相处很多年,而且隔三差五就要改。
这种代码值得打磨到90分。命名要讲究,结构要清晰,注释要到位,测试覆盖率要高。在这里花的每一分钟,未来都会以”少踩坑”的形式还给你。在这里偷工减料,就是给三个月后的自己埋地雷——而且你一定会忘了雷在哪。
这里省时间就是欠债。技术债这玩意跟花呗一样——不是不用还,只是利息高得离谱,而且越拖越想假装看不见。
第二象限:低变更频率 + 长生命周期 = 基础设施代码
数据库连接池、日志框架、部署脚本——这类代码写好了可能几年都不用动,但一动就是大事。
对这类代码,花时间写测试比花时间写优雅代码重要得多。 它不需要多好看,但需要非常可靠。就像你家的水管——你不会在乎水管好不好看,但你绝对不能让它漏水。
第三象限:短生命周期代码 = 出租屋
实验项目、demo、一次性数据脚本、活动页面、内部工具的原型——这些代码的共同特点是:活不过三个月。
60分能跑就行,别犯代码洁癖。 变量名不够优雅?忍了。没有单元测试?活动页面写单测,就像给一次性筷子刷油漆。代码有点重复?复制粘贴这种事,你在Stack Overflow上干得还少吗?三个月后,这段代码就是git log里的一行墓志铭,你花在它身上的每一分钟精致,都是不可回收的沉没成本。
这不是鼓励你写烂代码。这是让你把有限的精力花在值得的地方。
记不住矩阵也没关系,拿不准的时候就问自己三个问题:这段代码三个月后还活着吗?除了你还有谁会读它?它出bug会不会炸? 三个问题答完,该花多少力气心里就有数了。
代码质量不是越高越好,而是”恰到好处”最好。 就像做菜放盐——少了没味,多了齁嗓子,刚刚好才是手艺。

那3小时,本该花在哪?
回到开头那段被删掉的支付回调代码。
说来惭愧,那个支付渠道的合作谈判还在进行中,功能随时可能被砍——这个信息我当时是知道的。但代码洁癖发作的时候,理性判断就退居二线了,就像程序员看到tab和space混用时根本不可能继续往下看一样——那种生理不适,驱动我花了3小时去做一件投入产出比极低的事情。
而与此同时,我们的核心订单模块已经三个月没人加过测试了。
代码洁癖不是病。不分场合的代码洁癖才是。
下次忍不住想重构一段”丑代码”的时候,先掏出决策矩阵:它活多久?谁会碰它?出事有多疼?想清楚再动手,你就已经赢过了80%还在无差别重构的程序员。
好的工程师不是写出最干净代码的那个,而是知道什么时候该干净、什么时候该”先跑起来再说”的那个。 判断力这东西,比任何设计模式都值钱。