8

代码无可避免腐化是因为这 5 个原因

 3 years ago
source link: https://zhuanlan.zhihu.com/p/371279371
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

代码无可避免腐化是因为这 5 个原因

problem solver

我们会用不好阅读,维护不好等模糊的理由搪塞过去。但隐藏在类似表面症状的背后是非常丰富的深层次原因。

1、经济规律

你有没有想过资本家为什么付钱给你开发软件?是为了通过新代码维护已有的利润赚取更多的利润。这条简单的经济规律可以回答很多现象:

当你使用 npm module 遇到依赖问题的时候,你不禁想要骂人。当你使用 webpack 打包代码遇到问题的时候,你不禁想要骂人。但是没有人可以改变这个现状,因为开源经济规律。npm 体系,webpack 体系是开源的,免费的。任何新的技术要先达到已有技术一样的功能,其超出的部分才能产生“资本增殖”。资本家是不会为不赚钱的重写买单的。所以我们的技术栈就会越堆叠越高,总是在已有的技术栈上将就。

当你开始一天的工作的时候。你是不是默认在昨天的代码上进行修改?为什么?因为软件是软的,大家默认了今天的功能就是在昨天的实现上做增量的修改。但是我们不会在已有的一座双车道桥梁上增量修改为四车道。这就是软件是软的带来的经济规律。

我们不但会复用开源生态,会复用昨天的代码,我们还会为其他人提供“可复用”的东西。比如一开始我们没有想着要让最终用户也参与业务逻辑的定义。但是某天,新需求就是要给系统增加用户自定义促销公式的功能。这种在现有的软件代码基础上再架一层出来,给最终用户提供可编程性的做法已经司空见惯了。但是这也造成了“浮沙之上筑高台”。建筑行业需要先知道盖多高,然后先打对应的地基。而软件开发呢,鼓励 choose boring technology,反正也不知道将来需求会整出什么幺蛾子。

2、实现集成的产品需求

大师们喜欢谈解耦。大家都知道要解耦。问题是需求就是耦合的啊。解耦从来不是问题,任何两份代码,两个进程都可以劈开。如何在解耦的前提下实现产品经理花式集成的需求才是问题。但是大师们贩卖微服务架构,ECS架构的时候,是不怎么爱谈这些具体的业务的。

产品经理希望订单详情页上展示各种各样的信息。产品经理支付完成之后,做这又做那。产品经理希望融合各种数据流做AI。不是把一张数据库表用 CRUD 封装起来就能解耦合了的。如何实现产品经理的这些集成需求,集成的代码是写在了同一个 controller 里,同一个 git 仓库里,还是同一个进程里,这才是导致代码腐化的关键问题。

3、逐渐丧失除锈的能力

因为我们用“腐化”这个隐喻,所以这里用了“除锈”这个更形象的说法。一般我们更常说的是代码是不是有测试,是不是能够有信心的重构。

可能是因为本地内存不够,跑不起来所有的代码。或者部署脚本很脆弱,本地搭不起环境。或者因为缺少生产环境的数据,无法重现bug。或者因为关键的依赖只能在生产环境有。或者因为代码部署在了客户的设备上,我们连远程访问都不行。总之,代码写着写着就无法被简单的重构了。任何一个改动,都要变成一个大项目来推动。

逐渐丧失除锈的能力不是简单的用多写单元测试可以回答的,也不是Infrastructure as Code可以回答的。这背后的矛盾是集体和个人的矛盾。软件项目的开发者做为一个集体,他们的职责仅仅是维护“生产环境”。任何不是发生在生产环境的问题,都无法调动整个集体,因为不在每个人的 Job Description 中。当生产环境越奇葩(比如客户的设备,隔绝的网络),或者参与的开发者越多,这样的矛盾就会越尖锐。

4、固化的边界

当我们把一个“升级单元”,拆分成两个“独立可升级单元”。这个时候,两者之间的 API 就必须保持升级之后的向前向后兼容性。v1 的客户端,访问了 v2 的服务端,不能报错,还要能正常工作,才能满足“独立可升级”的约束。这就导致了边界的固化。当 devops 运动要求开发者对线上服务的稳定性负责的时候,这种要求就驱使了开发者把“故障定位边界”等同于“独立可升级部署边界”。说白了就是不希望给其他人擦屁股,我只管我范围之内的稳定性。这也造成了大量之前隐形的软性的边界被固化成了“微服务”。

当我们把微服务更进一步和组织架构对应起来的时候,这种固化的边界会更明显。具体原因大家都懂,这里就不赘述了。

固化的边界就像我们每个人逐渐硬化的血管一样,总有一天会把我们埋于黄土。

5、内隐知识(Tacit Knowledge)

内隐知识的意思就是关于遗留代码的一些知识是无法被文档,被注释给传达出来的,它是内隐在当初这份代码作者的脑袋里的。有一篇很有名的文章《Programming as Theory Building》就是讲这个问题。

我们有另外一个不用证明的定理,就是软件最初的开发者总是会逐渐离开这个组织。无论是因为觉得待遇不理想,工作委屈了跑路了。还是因为年龄太大退休了。他们总是会走的。

当总是有一些知识是内隐知识,而开发者又不可避免会离开的时候,那这些内隐知识也就跟着走了。对抗这个趋势的唯一办法就是让新人来重写,让他们获得这些内隐的知识,然后祈祷这些新人可以多留在组织内一段时间,不要跑路得太快了。

连发三篇劝退文章为哪般?

连同本篇,5.1假期之后我已经连发了三篇劝退文章了(软件开发提效哪有那么容易,都是坑啊~在提赋能之前,先想想这5个问题)。

热心的朋友们会好心规劝你,别整这些没有用的东西了。他们会说软件开发的真相就是要不断重写。软件开发的要义就是唯快不破。软件怎么开发都是次要的,关键是要商业成功。整这些玩意不会帮助商业成功,商业成功了一切做法都会自带光环,而被无数人顶礼膜拜。

确实,软件工程能带来的降本增效相对于其他工程来说,微不足道。不要指望软件工程技术被拔高到其他工程一样的重要地位,从收益的角度来说支撑不了。但丰富的社会应该是多元的,每个人都可以追求一些自己觉得有意思的东西,即便看不到多少“收益”。

世界上只有一种真正的英雄主义,就是认清了生活的真相后还依然热爱它 - 罗曼·罗兰


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK