祖传代码,从字面意思来看,便是一代代老程序员们留下来的“宝藏”代码——这些长年累月的代码中存有很多隐患,后来的“接盘侠”们要么无从下手,要么一改就崩,险些可以说是程序员们的“终极噩梦”,因此也被称作“屎山代码”。

这不,最近又有一个“晦气蛋”火上了HN热榜:“我继续了我见过的最差的代码和技能团队,该怎么办?”

01 拥有12年历史、没有版本掌握的“祖传代码”

PHP祖传代码12年的家传屎山代码年收入竟超14亿元 Docker

从这位“接盘侠” @whattodochange 阐述的现状来看,他这次继续的代码历史长达 12 年,是没有版本掌握的 PHP 代码,居然每年还能产生超过 2000 万美元(约公民币 1.4 亿元)的收入:

这些代码每年能产生超过 2000 万美元的收入。
运行在 PHP 上。
已经在生产环境直接开拓了 12 年,没有源代码掌握(都是像 index-new_2021-test-john_v2.php 这种)。
没有利用 composer 或任何依赖管理,都是 require_once。
没利用任何框架。
路由管理完备是在 NGInX 中重写的(NGInX 的配置大约是 10000 行)。
这些年只在不断往上堆代码,没删除任何代码(我推测这是由于代码是直接在生产环境开拓的,删东西太危险了)。
数据库构造也是一片混乱,没有迁移等等。
要添加一个列时,由于数据量大,他们一样平常会建一个新表,然后用 join。
JS 和 CSS 也是如此。
jQuery 的不同版本相互斗殴,详细取决于你在哪个页面,有时乃至同一个页面也会有。
当然没有 MVC 模式或其他模式什么的,没有模板库。
这是 PHP 2003 的样式。
在很多地方,我看到像是 Controller 一样的文件,向它自己的 rest API 发出 curl 要求(通过域名而非 localhost)进行 oauth 授权等…然后只是为了获取菜单项或产品列表。
没有缓存(但有 memcached ,但只用于 Session…)。
团队只有 3 个很年轻的人,一个后端,一个前端,一个 iOS/android ,他们对代码变革非常抵触。
生产力很差,这可以理解——乱七八糟的东西实在是太多了,根本没办法做新东西。

以上便是 @whattodochange 目前所接盘的代码和团队现状,他头疼道:“我必须要找到一个策略来修复这个开拓团队。

面对这个“烂摊子”,@whattodochange 想到的办理办法是完备重写,但由于公司管理层和总部对这些阻碍成分并没有真正理解,业务部门对这个项目有非常积极的方案路线,且疫情之下公司的预算很紧张,导致 @whattodochange 根本无法推进。

因此,@whattodochange 发帖乞助:“我知道完备重写是必要的,但要如何平衡?”

02 逐一改动 or 摆烂跑路?

对付 @whattodochange 的遭遇,不少有履历的程序员深有同感,也提出了一些应对“祖传代码”的详细建议。

“完备重写不是必需的,乃至可能是最糟糕的方法。
可以一次做一件事,终极你会重写所有代码,但永久不会陷入‘完备重写’的陷阱中。

不过在重写一行代码之前,记得要做大量的测试。
如果有端到端测试,这些测试运行在客户群当前利用的每个功能中,那么您就有一个基线来安全地进行变动。
只要测试通过,就可以删除代码。

不要想着去推动变革,考试测验拥抱这个每年赚 2000 万美元的恐怖代码库,和团队谈论谈论如何在能力范围内改进即可。

作为这个开拓团队的经理,你的任务是要得到高管支持来逐渐办理这个烂摊子。
你没必要见告高管或团队详细要如何修复,只要有韶光和空间上的支持就好。

有一种办法是每周五凑集团队一起来测试,但可能会常常被紧急任务挤掉;另一种办法是让每个更新的发布速率稍慢一些,这样就有韶光优化每次更新所涉及到的其他代码。
例如,业务哀求添加功能 X,那么你就给干系的现有功能 Y 添加一个测试,可以对团队说优化 Y 是为了让添加 X 更为方便。

不过,也有部分程序员在理解 @whattodochange 的现状后,认为“摆烂跑路”是最优解:

“你该当考虑辞职。
虽然你知道这代码很烂,但它确实能带来每年 2000 万美元的收入,以是你的团队不想变革,业务职员也不会关心代码质量。
他们会认为:反正 2003 年样式的 PHP 代码就可以实现这个收入,那不挺好,干嘛要摧残浪费蹂躏财力和精力去重写?

末了,你很难说服你的开拓团队和业务部门赞许重写这个决定,乃至还会招来仇视,而你自己也会讨厌这样的事情氛围。

“为了避免自己受伤,我劝你摆脱这种混乱的处境。
我之前也一贯处于类似的情形,花了快五年的韶光试图办理,但末了还是心累地放弃了。

03 血泪教训:人跟代码有一个能跑就行了

其实在现实中,险些所有软件开拓公司都有各种老大难的“祖传代码”,像 @whattodochange 碰着这种 12 年历史的都还算年轻的了——一样平常越大规模越厉害的公司,“屎山”代码的情形越严重。

《GTA 5》联机版中循环 19.8 亿次的 if 语句,被许多人称作游戏开拓史上最大的“屎山”代码,存在了 7 年 R 星(游戏开拓商 RockStar)的程序员无人敢动。
终极,还是一位黑客大哥看不下去给出理解决方案,R 星这才官宣要修复 bug,并给这位黑客褒奖了 1 万美元。
一位亚马逊工程师也曾形容他们公司的代码为:“一座很大的屎山,一座你见过的最大的山,每次你想改动一个 bug,都得爬到屎山的正中心去。

类似地,海内也有许多程序员分享过他们碰着的各种“骨灰级”祖传代码:

“公司代码已经 40 年了,最早写代码的人不知道是否活着,要命的是文档没留下,项目代码堆在一起能有 90 多 G。
”“我要升级的那批代码写于 2000 年前,最早的部分可能写于 1980 年代贝尔实验室。
第一批掩护升级做需求的人早就退休了,第二批也退休了,每一行代码动起来都胆战心惊。
”“曾经在 Visa 事情过,觉得什么 10 年 20 年的代码切实其实 naive,你见过 1965 年的代码吗?第一次看到切实其实惊呆了,这半个世纪的代码现在还在用还跑的好好的?”

可能对付很多刚事情的萌新程序员来说,瞥见这些各处都埋着“地雷”的代码第一反应便是“推倒重来”,但大多都得到了血泪教训:“有的时候,代码能运行就不要考试测验去改,哪怕是碰着屎山一样的代码”,可能还会对新人建议道:“人跟代码有一个能跑就行了。

那么,你是否在事情中遇见过令人发指的“祖传代码”,最长拥有多少年历史?你是选择逐一改动还是放任不管?