程序开发者去世,代码没人懂,一个bug导致千万损失

作者丨RajivPrabhakar
译者丨盖磊
策划丨田晓旭、Tina
系统出故障了 。 当年负责写这个程序的开发者早在十五年前就去世了 , 现在已经没有人能读得懂他的代码了......
现在一些关键系统的运行仍依赖于过时的软件 , 但编写他们的人要么离职要么已经去世 。 中间也缺少维护或更新 , 导致现在几乎没人能理解它们 , 而且一旦出现Bug就会给企业造成不可挽回的损失 。
而现实中的这种例子 , 远比你想象中的要多 。
一个令人深思的故事
我的一位客户负责数项世界排名前一百的养老基金 , 该公司在前几个月成功的将程序搬到了云端 。 作为项目的主任架构师 , 前两天我很意外地直接收到了CIO的短信:“抱歉打扰 , 我们出S1X级的大问题了 。 你能下午飞过来吗?” 。
程序开发者去世,代码没人懂,一个bug导致千万损失
文章图片

“S1X”是他们对“比最严重级别还要糟 , 级联影响到业务其它非直接相关部分”问题的定义 。
事情看起来十万火急 , 当天晚上我就飞到现场进行了诊断 , 发现是该客户的系统中一个批处理任务发生了崩溃 。
该任务每天晚上执行一次 , 通过写一个CSV文件为某些养老金计算缴费率 , 再将计算的结果输出到另一个收益(benefit)分配程序 。 原先收益分配程序设定为在缴费(contribution)低于预测(projection)时会向客户发出报警 。 由于上一个处理任务已发生崩溃 , 不再产生输出 , 因此程序认为“所有缴费为零” 。
所以系统立即向该养老基金的经理们发出大量警报邮件 , 基金经理们被吓得赶紧从该项目里撤离了 。
起初没有人找得出问题发生在哪里 , 在大家的记忆和工作记录中 , 这个批处理任务也从未崩溃过 。 编写该批处理程序的人已经在15年前离世了 , 并且数十年前就不再是该企业的员工了 。 尽管该批处理的程序代码规模不大 , 但非常难读 。 因为在编程时主要考虑的是提高计算效率 , 并未考虑如何适合他人阅读 。 当然 , 程序也没有留下任何测试 。
事故发生的前一天 , 脚本在运行环境中的编排发生了一次更改 。 这被认为是导致事故的罪魁祸首 。 幸运的是 , 这个更改做了版本push , 工程部门据此回溯到先前的版本 。 但不幸的是 , 这只使事情变得更糟 。
最后我们通过提供热修补脚本的方式解决了这个问题 。 但实质上这次崩溃已经给该基金造成了170万美元(约1203万人民币)的直接损失 。
“数据溃烂”(BitRot)问题
事实上类似的故事并非孤例 。 我在2012年离开英特尔加入Sun公司 , 切身体会到他们的SPARC产品线做得是多么的糟糕 。 Sun在互联网泡沫时代的杀鸡取卵行为 , 导致此后SPARC远远落后于英特尔的至强产品线 。
我的经理都和我说 , 要在英特尔至强服务器上运行模拟程序 , 因为SPARC服务器“非常慢” 。 更严重的问题在于 , 英特尔不仅CPU性能更好 , 而且具有制造优势 , 这意味着CPU的制造成本也大大降低 。
随之而来的问题很明显:既然远远落后于竞争对手 , 那么为什么客户还是会购买我们的SPARC芯片?一位高级架构师向我给出了令人震惊的答案 。 那是因为我们的客户的软件系统过于僵化 , 只能在SPARC/Solaris系统上运行 。 而迁移到x86/Linux对客户而言是一项艰巨的任务 。 许多客户甚至丢失了源代码 , 无法重新编译应用 。
他们能做的最好选择 , 就是升级到最新一代的SPARC处理器 , 无论这样的处理器性能多慢 , 价格多么昂贵 。
这就是问题所在 。 我们整个部门的业务模式 , 完全围绕着这个国家中那些溃烂的软件系统 。
维持运转的代价
我加入Amazon后 , 发现自己面对正是这样一个为遗留系统而构建适用的原型 。 该系统是另一个团队基于大量技术债务开发的 , 并且团队早已解散 。 之后该项目的所有权就移交给我们的团队……事实操明 , 这并非揽下一件好事 。 所以开发人员陆陆续续跳槽到其他的团队 。 我加入时的十多名团队成员中 , 一年后一位都没有留下 。
该系统从表面上看并非一无是处 。 它使用了现代编程语言和技术栈(Java8)编写 , 由拿着六位数收入的开发人员所组成的团队进行着日常维护 , 并不断更新以修复错误和添加新功能 。 尽管如此 , 测试修改(turnover)依然是拖累整个系统的显著负担 。 所有权变更和团队更替导致整体代码设计、端到端功能、最佳实践和调试技术等大量实操知识的丢失 。 尽管我们一直努力保持项目的推进 , 但感觉就像进入了一片沼泽地 , 四处亡羊补牢 , 深陷战争迷雾(FogofWar)中 。
设想一下 , 一个运行在第一版Java上的项目 , 开发活动几乎为零 , 没有开发人员负责 。 还有比这更糟的项目吗?
如何预防发生灾难性故障
软件开发人员致力于构建健壮、无错误的系统 , 无需过多人工维护就能正常运行多年 。 据此标准 , 上面所说的养老金脚本无疑是非常成功的项目 。
然而现实很严峻 , 再好的项目有发生崩溃的一天 。 最终 , 所有内容都需要做更新 。 导致原因可能是:
系统运行所基于的硬件系统停产了 。
系统的依赖关系不再可用 。
依赖关系中出现了严重安全漏洞 , 而唯一可用的安全补丁仅适用于并不后向兼容的版本 。
应用开发基于一些已不再成立的假设 。
甚至是整个世界发生了改变 , 软件必需因势而变 。
无论出于何种原因 , 变更都是不可避免的 。 唯一的问题是 , 当最终需要变更时 , 它的代价有多大 。
对于一个活跃维护的系统 , 变更就不会那么痛苦 。 但是 , 对于一个已有几年甚至数十年没有维护的系统 , 那么很多因素都可能会导致灾难性的错误 。 例如:
构建系统的开发人员已经离职 。
源码丢失 。
开发人员不了解如何正确地编译源码 , 并构建可执行文件 。
开发人员不了解如何部署系统 。
开发人员不了解如何正确地配置运行可执行文件 。
开发人员对代码的架构和实现一头雾水 。
开发人员不了解使代码功能正常运作所依赖的常量和隐含假设 。
开发人员不了解如何运行自动化测试 。
开发人员不了解如何调试测试问题 。
开发人员不了解如何调试生产故障 。
开发人员不了解如何获取生产日志和指标度量 。
一种解决方案是对上述问题做尽量详细的记录 。 但文档并非最优的解决方案 , 因为其中难免会有遗漏 。 再全面的文档 , 也比不上自己亲自动手操作 。
理想的做法
一个好的开端 , 就是企业指定专门的开发人员全面负责上述所有问题 。 但这还不够 。
如果仅仅反复“阅读文档” , 那么就会产生厌倦 。 人们并不能从中获得实践经验 , 进而解决实际问题 。
如果加上“绩效审核” , 那么人们更倾向于新的出彩项目 , 很有可能会简单地抹去并掩盖旧的问题 , 甚至直接从中剔除问题 。 如果没有真正面对的可交付成果或挑战 , 许多人自然会选择一条最轻松的道路 。
真正要想避免软件发生溃烂 , 唯一的方法是确保项目的持续推进 , 即使看起来毫无必要 , 或是存在风险 。 建立、维护和验证实操知识和能力的最佳方法 , 就是不断做出变更 , 并测试这些变更是否能成功地执行 。 一旦项目停止推进 , 那么相关实操知识就会过时和消解 。
即使原地打转听上去很可笑 , 但这对疏于维护而言仍是一种进步 。 事实上 , 维护人员总是可以做一些事情实现向前推进 , 虽然步伐可能很小 。
一种做法是使用所有依赖关系的最新版本去更新开发环境 , 例如:
从JDK8迁移到11 。
更新JVM , 使用G1垃圾回收机制替代原先的CMS 。
将GCC编译器从版本5更新到7 。
将数据库从Postgres9.5更新到Postgres11 。
将AWSSDK从版本1.10更新到1.11 。
在生产环境中安装最新的Linux发行版 。
在一些情况下 , 依赖关系会过时 。 这时就需要考虑整体迁移到新的架构 。 例如:
从SPARC迁移到x86;
从Solaris迁移到Linux 。
同样 , 保持开发人员的战斗力 , 可对应用做如下更新:
修复顽疾和一些边缘用例 。
加固自动测试套件 。
清理技术债务 。
做性能优化 。
实现新特性 。
增量重构代码库 , 改进可读性 。
上述变化势必会带来暂时性风险 , 并产生看似“不必要的”支出 。 开发人员难免会犯一些错误 , 甚至引入新的错误 。 面对这些代价时 , 人们很容易退而求其次 , 认为“如果还没有破裂 , 就不要修复 。 ”
对于一个业务价值不大的系统 , 这可能是合理的做法 。 但对于任何关键任务系统而言 , 忽略问题将仅会掩盖较小的瞬态风险 , 而没有解决永久的灾难性风险 。 一旦有一天需要紧急调试或更新系统 , 那么企业将无所适从 。
对于任何关键任务系统 , 至关重要的就是维持实操知识和能力 。 做到这一点的唯一方法 , 就是不断地开展实操 。 企业的大脑和肌肉一样 , 不使用 , 就会失效 。
作者简介
RajivPrabhakar , 毕业于密歇根大学和斯坦福大学 , 之后曾在Intel和SunMicrosystem公司工作五年 , 参与了Jaketown、Skylake和SPARC设计团队 。 之后转向软件相关工作 , 先后任职于Amazon、Google、EngineersGate , 并数次自己组建创业公司 。
参考阅读:
https://software.rajivprab.com/2020/04/25/preventing-software-rot/
为你推荐
【程序开发者去世,代码没人懂,一个bug导致千万损失】InfoQPro是InfoQ专为技术早期开拓者和乐于钻研的技术探险者打造的专业媒体服务平台 。


    推荐阅读