【CSDN 编者按】在软件开发领域,“遗留”一词常常与老旧、难以维护的代码联系在一起,成为许多开发者心中挥之不去的阴影。然而,本文作者提出了一个新颖而深刻的观点:真正的问题并不在于那些看似过时的技术堆砌,而是我们对待这些代码的态度和处理方式。
“遗留”这个词在软件工程中被过度使用,且带有负面色彩。在这篇文章中,我将论证一个观点:问题不在于软件,而在于人。也就是说遗留下来的不是代码,而是我们看待代码的方式,且这种方式会导致无助感和高昂的重写成本。
代码是如何变成遗留代码的?
当人们对某些代码不满意时,就会称之为遗留代码。通常情况下,这仅仅意味着这些代码不是他们编写的,因此不理解这些代码,也不敢轻易修改这些代码。有时,这也意味着代码质量低劣或使用了过时的技术。有趣的是,在大多数情况下,“遗留”标签的使用更多反映了贴标签的人的观点,而非被贴标签的代码本身。也就是说,如果原始作者还在场,那么这段代码根本不会被视为遗留代码。
根据这一思路,我们可以推断出促进或防止代码成为遗留代码的因素:
1、程序员的任期越长,代码成为遗留代码的可能性就越小,因为原始作者会在场欣赏并维护这些代码。
2、代码架构越好、清晰度越高,相关文档越详尽,代码成为遗留代码的可能性就越小,因为作者很有可能成功地将代码转移给新的负责人。
3、公司越频繁地使用结对编程、代码审查和其他知识转移技术,代码成为遗留代码的可能性就越小,因为除作者之外的其他人也会了解这些代码。
4、公司培养初级工程师的能力越强,代码成为遗留代码的可能性就越小,因为培养初级工程师的最佳方式之一就是让他们负责组件的所有权。
5、公司使用简单标准技术的程度越高,代码成为遗留代码的可能性就越小,因为这些技术的知识在组织内部广泛传播。具有讽刺意味的是,如果把创新定义为采用新技术,那么团队越是创新,遗留代码就越多。每次团队采用新技术时,要么新技术行不通,新尝试就会成为遗留问题;要么新技术成功,旧系统就会成为遗留问题。
遗留代码之所以如此普遍,是因为大多数团队在上述所有方面都不够优秀,无法避免遗留代码的产生——但也许,你可以做到。
做一名优秀的工程师,不要制造遗留代码
如果我们不想收拾别人的烂摊子,那么合理的做法就是我们自己也不要给别人留下烂摊子。
(1)不要编写糟糕代码
我对“糟糕代码”的定义是:无法转移给新的负责人、必须重写的代码。出现这种情况的主要原因是代码不够清晰,这可能源于简单的不称职,如架构不佳或缺乏测试,也可能源于开发人员无意识地采用了适得其反的方式。其中最具破坏性的两种趋势是:认为好的代码不需要注释,以及认为代码必须使用复杂技术,如微服务或冗长复杂的架构模式。
为了避免自寻烦恼,我喜欢用的启发式方法是问自己:“最简单可行的方法是什么?”然后,我只会在解决实际问题时才使事情复杂化。只需一个简单的问题,就能轻松击溃过早采用微服务这样的馊主意:“这解决了什么问题?”如果没有好的答案,就不应该去做。
(2)不要“创新”
很多工程师认为创新就是采用现代技术,比如新的框架和语言,但这种错误观念会产生大量的遗留代码,因为一旦我们开始用 Go 语言编写新服务,所有用 Javascript 编写的现有服务都会变成遗留代码。
相反,我认为创新是解决新问题或以更好的方式解决旧问题。如果你采用的新技术做不到这一点,我不认为这是创新,而是在浪费别人的钱。这是一种假“创新”,它不仅没有解决问题,反而创造了新的问题,实在很浪费!
请注意,我并不是说你永远都不能采用新的语言。我只是说,它必须能解决实际问题,而且应该是解决问题的最佳途径。例如,如果你要花数百万美元用 Python 来训练一个机器学习模型,那么用 Rust 来重写它可能会更省钱。
(3)教导他人
正如我之前所说,代码成为遗留代码的最常见原因是创建者离开了,而新的维护者无法理解代码。编写良好的代码固然重要,但教导新人更重要。老实说,大多数专业程序员都写不好代码,但他们都能教同事一些代码的工作原理。这个过程不仅对学习者有益,对老师也有益,你会发现解释自己的代码会让你反思,从而成为一名更好的工程师。最后,指导是高级及以上程序员的核心技能,因此培养这一技能对你的职业生涯也有好处。
最好的教学形式就是结对编程。新手在 2 小时的结对编程中修复一个棘手的 Bug 可以学到很多东西。更理想的是在编写新代码时结对编程,这样所有权从一开始就共享。第二好的教学形式是代码审查,虽然效果稍差,因为它速度较慢、异步且需要书面沟通,而人们在这方面往往表现不佳。此外,它还需要一个有品味且挑剔的审阅者,而这类人并不多见。
(4)体面地离职
优秀的工程师不仅要建立优秀的系统,还要确保这些系统能够持久运行。他们通过持续地教导他人,尤其是在计划离职时,确保系统得到妥善维护。例如,他们会提前一个月或更长时间通知,并利用这段时间培训其他人并编写文档。
处理他人的遗留代码
尽管我们自己不会制造遗留代码,但在职业生涯中难免会遇到,因此我们需要知道如何最好地管理它们。
(1)并非一切都是遗留代码
我只对那些我们不了解、难以改变的系统使用“遗留”这个词。如果一个系统仅仅是老旧,但运行良好,使用“遗留”这个词会带来不必要的污名,还可能导致不必要的重写。
如果一个系统正在进行积极开发,我们不需要给它贴上任何标签。如果它的开发进度缓慢或停止,我们可以说它处于维护模式。
(2)解决遗留代码
由于遗留代码的问题在于维护者不理解它,你可以通过学习来解决这个问题。你可能仍然会觉得这些代码很糟糕,但能够逐步改进它,添加新功能,编写测试。这看起来可能没有使用热门新事物进行全面重写那么有魅力,但这对公司来说是正确的做法,而且如果我们坚持做正确的事,我们就会因此赢得声誉和回报。
在极少数情况下,遗留系统确实无法挽救,应该被抛弃,但只有在你深入理解系统及其问题后才能确定这一点。也就是说,你需要尝试解决遗留代码几个月后,才能决定重写是最好的选择。
判断是否需要重写的一个很好的启发式方法是,我们是否坚信修复系统比重写系统要花费更多的精力。请注意,除非我们深入理解当前系统以及重新编写新系统的成本,否则我们无法确定这一点。
(3)面对或逃避
总有人需要修复遗留代码,但这个人不一定非要是你。与其领导一次误导性的重写,不如换个项目或公司更为光荣。
如果你坚持下去,你可能会觉得这将是一个看不到尽头的痛苦过程,但一年后你会惊讶地发现情况会好很多。此外,你还可以让更多的年轻人参与进来,并将所有权移交给他们。对你来说枯燥乏味、吃力不讨好的工作,对初级工程师来说可能是一个令人兴奋的机会。
总结
大多数公司都有许多遗留系统。无能的程序员创建了这些系统,然后把烂摊子留给下一个人。而那个幸运的接班人又缺乏道德修养,无法解决这个烂摊子,于是重写了一切,循环重新开始。
你可以打破这种循环:注意不要创建遗留系统,并解决你遇到的遗留系统。你会因此成为一名更好的工程师,市场也会认可你是一个解决问题而不是制造问题的人。你的声誉会越来越高,从而得到丰厚的回报。