造轮子的真正代价不是开发,是走不掉

博客分类: 

每个技术团队都会经历这样一个时刻:现有工具不太顺手,自己做一个吧。

理由总是充分得无法反驳——市面上的组件库不支持我们这种交互模式,开源的表单引擎处理不了我们的动态字段逻辑,第三方的配置中心满足不了我们的合规要求。每一条拿出来都是刚需,每一条都指向同一个结论:我们得自己造。

没人会在这个阶段反对。因为反对意味着你要证明"现有的东西够用",而提出造轮子的人已经把"不够用"的场景摆上了桌面。你没办法反驳一个正在发生的痛点。

于是轮子开始转。第一周,大家很兴奋。第三周,初版出来了,确实比之前好用。第二个月,几个业务接入了。半年后,团队里有一半人的KPI跟这个轮子挂钩。一年后,最初写轮子的人提了离职。

这就是造轮子的故事。但今天我不想聊"该不该造"——这个问题已经被讨论过太多次,而且答案永远是"看情况"。我想聊的是一个更少人关注、却更致命的问题:造轮子最大的代价不是花时间开发,而是你再也走不掉。

 

开发成本只是首付

 

大部分人评估"要不要自己造"的时候,脑子里算的是开发成本。两个人做两个月,能搞定,成本就是四个人月。和采购方案比一比,好像更划算。这个算术本身没错,但它只算了首付。

真正的问题是后面几十年的月供。

一个内部工具一旦上线,它的成本曲线不是一条水平线,而是一条不断上升的抛物线。第一年,维护成本很低,bug偶尔修修就行。第二年,业务提了新需求,原来不支持的功能要加上去,架构得改。第三年,基础设施升级了——Node.js大版本更新、React新API、构建工具换了一茬——你的轮子也得跟着改。第四年,原来写轮子的那批人已经走得差不多了,新来的人看着代码库发呆。

这还是运气好的情况。运气不好的话,第二年就开始崩。

很多团队对维护成本有一种不切实际的乐观,觉得"做完之后就是稳定运行,不需要太多投入"。偶尔会是这样——如果你的轮子足够简单、足够边界清晰、足够不依赖外部环境。但大部分内部工具做不到这一点,尤其是那些和数据打交道的工具。业务变一次,工具就得跟着变。你以为是工具在服务业务,实际上工具已经被业务绑架了。

在金融业务里,这种情况尤其明显。产品规则变了、合规要求变了、推荐逻辑变了,你的内部工具就得跟着改。而每一次"跟着改"都在给这个工具增加重量,让它离"可以替换"越来越远,离"不得不维护"越来越近。

 

人才锁定:最贵的隐性成本

 

开发成本可以估算,维护成本可以接受,但有一种成本大部分团队根本没意识到——人才锁定。

内部工具最大的特征是:只有造它的人最懂它。

开源项目有社区,有文档,有Stack Overflow上的问答,有一大群人在踩同一类坑。你的内部工具只有那两三个人的脑子。他们知道为什么要这样处理边界条件,知道这个hack是为了绕哪个上游服务的bug,知道这个配置项的默认值为什么不是0而是-1。这些全都在他们的脑子里,不在任何文档里——因为内部工具很少有完善的文档,即使有,文档也很少能跟上代码的变化。

这意味着什么?意味着这几个人变成了人肉接口。所有跟这个工具有关的问题都要找他们,所有需要改动的需求都要经过他们,所有线上故障的排查都离不开他们。他们成了这个工具的"活文档"和"唯一运维"。

这还只是日常的麻烦。真正的灾难是:当这些人要离开的时候。

我见过一个场景:团队花了大半年做了一个内部的状态管理框架,用了两年,覆盖了四五个业务线。后来核心维护者跳槽了,留下一个没有文档、没有测试覆盖、注释半中文半英文的代码库。接手的人花了三个月才搞清楚基本逻辑,又花了三个月才敢做第一个小改动。这六个月的成本,当初造轮子的时候谁算过?

更要命的是,人才锁定还会产生一个恶性循环:因为只有少数人懂,所以只有少数人能改;因为只有少数人能改,所以大部分人不愿意碰;因为大部分人不愿意碰,所以懂的人越来越少。等到你想摆脱这个轮子的时候,你发现能做这件事的人已经只剩下一个了——而他正在准备离职。

 

生态脱节:你在原地,世界在跑

 

造轮子的时候,你觉得自己在解决问题。三年后回头看,你发现自己挖了个坑。

开源方案的问题是它不完全满足你的需求。但开源方案有一个内部工具永远比不了的优势:有整个社区在替你迭代。

你造了一个内部表单引擎,支持了你需要的所有字段类型和校验规则。第一年,它比antd的Form强多了,因为antd不支持你们那种嵌套动态表单。第二年,antd升级了,支持了更多动态场景,而你的引擎还是一年前的版本——因为这一年里没有人专门维护它,需求在往前走,工具还在原地。第三年,你的引擎已经明显落后于社区方案了,但迁移的成本太高——四五个业务线在用,接口不兼容,数据结构不一样,动一下就是全链路的改造。

这种"生态脱节"是缓慢发生的,像温水煮青蛙。刚造出来的那段时间,你的方案可能确实比开源的好用——毕竟它是为你的场景量身定制的。但随着时间推移,社区在飞速进化,你的工具慢慢变成了一个时间胶囊:它冻结了造轮子那一刻的技术认知和业务需求,而对之后的一切变化都反应迟钝。

React 18出了并发模式,你的引擎还在用class组件。TypeScript 5.0出了更好的类型推导,你的类型定义还是any满天飞。Vite取代了Webpack成为主流构建工具,你的构建配置还锁在Webpack 4。每一个脱节的点都不是大问题,但它们叠加在一起,就让你的工具变成了一个技术化石——还在运转,但没人愿意碰。

而在金融业务场景里,这个问题还会被合规要求放大。很多团队造轮子的初始理由就是"开源方案不满足合规要求",听起来很合理。但合规要求也在变化——两年前的合规标准可能是"数据不能出境",现在的标准可能已经细化到"个人敏感信息需要加密存储且支持用户授权撤销"。你的内部工具当初只是在"不出境"的前提下设计的,现在要支持更细粒度的合规要求,等于要推倒重来。而此时开源方案可能早就跟上了新的合规标准——因为社区里有无数像你一样的团队,他们也在面对同样的合规变化,只是他们选择了贡献代码而不是另起炉灶。

 

为什么走不掉

 

到了这一步,大部分人其实已经意识到内部工具成了负担。但意识到问题和解决问题之间,隔着一条巨大的鸿沟。

走不掉有三个原因。

第一个是沉没成本。这个工具已经投入了这么多人的时间,已经承载了这么多业务逻辑,已经上线了这么多场景。放弃它意味着承认之前的投入打了水漂——这对团队的心理冲击是巨大的,尤其是对当初拍板造轮子的那几位。

第二个是替换风险。从内部工具迁移到开源方案,意味着所有使用这个工具的业务线都要跟着改。在金融场景里,任何改动都有可能引发线上问题,而线上问题的代价是用户资金受损。没人愿意承担这个风险——"能用就行"变成了最合理的说辞。

第三个是没有人愿意做这件事。迁移内部工具是一项吃力不讨好的工作。做好了,业务没有感知——因为功能没变,只是底层换了。做坏了,全是你的锅。在绩效考核体系里,"把现有系统从内部工具迁移到开源方案"这种工作,产出的可量化价值接近于零。比起做一个新功能、上一个新的业务场景,迁移工作的存在感太低了。

于是这个轮子就继续转着。每转一圈都比上一圈更吃力,但你已经停不下来了。

 

我怎么看

 

我不反对造轮子。有些场景确实需要——尤其是在金融业务里,合规和安全要求会让很多开源方案根本不可用。但我反对不加保质期地造轮子。

什么意思?我建议每造一个轮子之前,先回答三个问题:

第一,这个工具两年后还在不在? 如果你觉得两年后会被更好的方案替代,那不如现在就去适配那个方案,哪怕多花一点时间。如果两年后它还得在我们系统里跑,那才有理由自己造。

第二,如果造轮子的人走了,还有谁能维护? 如果答案是"没有人",那要么扩大维护团队,要么不造。一个只有一个人能维护的工具不是资产,是定时炸弹。

第三,有没有可能把它开源? 开源不是做慈善,而是一种让工具接入生态的方式。开源了,就有人帮你踩坑,有人帮你迭代,有人帮你写文档。即使没人用,开源这个过程本身也会迫使你把代码写得更干净、接口设计得更合理——因为你知道别人会看到。

这三个问题不是万能的,但至少能让你在造轮子的兴奋期保持一点清醒。

造轮子不是问题,走不掉才是。而走不掉这件事,从来不是在你想走的时候才出现的——它在你说"我们自己做一个吧"的那一刻就已经开始了。

You voted 4. Total votes: 5

添加新评论