老鸟如何填坑修复遗留下来的代码库呢
摘要:只要在软件行业待得足够长,就不可避免会面临一个棘手的问题:修复遗留的代码库。遗留代码是很多程序员眼中的“大麻烦”,那究竟为什么如此“讨嫌”呢?
只要在软件行业待得足够长,就不可避免会面临一个棘手的问题:修复遗留的代码库。遗留代码是很多程序员眼中的“大麻烦”,那究竟为什么如此“讨嫌”呢?本文以一则寓言为引,写出了遗留代码的产生原因和解决办法——“我们不是遗留代码……我们是传奇。”以下为译文:
在一个不起眼的小角落里,有一段默默无闻的小代码。
它厌倦了别人叫它遗留代码,它厌倦了被人们遗忘在角落。毕竟,它还在负责一段业务逻辑。然而,尽管它处理了所有的交易,提供了许多价值,还帮助了许多用户,但还是免不了被人取笑。
小代码很难过。“我是这项业务的支柱!”它大喊道,然而没有人听到它的呐喊声。人们不愿理睬它,甚至不想与它互动。小代码经常听到有人用很刺耳的绰号称呼它。就在上周,有人接到了修改小代码的命令,但是那个人的话深深地刺痛了小代码。
“我不想碰小代码。它太丑了,不符合我们目前的做法。每次我碰小代码,就会走霉运。”一位团队负责人说。
小代码伤心地坐在角落里哭泣,然而它没有眼泪。后来,小代码决心振作,它觉得自己需要品牌推广。于是,它开始与其他代码交谈。虽然,小代码和其他代码并不是好朋友,但它们似乎总是在调用它。
“你好,微服务先生,为什么大家那么喜欢你呀?”
“哦,你好,”微服务回答,一边快速地瞟了一眼小代码,显然它想尽快结束这场对话,“可能是因为我们的目标很容易定义,我有测试覆盖率,而且我很容易部署。”
“哦,”小代码说,“都有哪些人负责你的工作呀?”
“整个团队。他们负责编写、重构,并将我部署到Kubernetes上,然后更新并自动扩展规模。”
“哇,听起来很有趣。什么是kubernetes?”小代码说,“你合适生产吗?”
“生产?”微服务回答道,“那是什么?”
“哦,不。”小代码回答道。
它意识到它正在与“最好的”代码交谈——这些代码在技术上是完美的,但对用户没有帮助性。我们的小代码获得了很多诸如此类的反馈。很多新系统都有新想法,但是小代码的职责是运行业务,过去是,现在是,而且将来也是。
在遭到一系列的碰壁后,小代码想了各种办法,并试图与另一个代码库交互。
“你好。你知道为什么人们不喜欢我吗?”
这个代码库体型庞大,而且好多天都没有刮胡子了。它看起来有点狼狈,但总得来说,它看上去很有智慧。
狼狈的代码淡淡地说:“当然没人喜欢你了,因为你是遗留代码。”
“没有必要当面给我难堪吧。”小代码说。
“不,不。遗留代码的意思是说,你负责运行业务。你有巨大的影响力。你承担着各种职责……但也意味着,与你愉快地合作的时光也已经随着那些伟大的人一起远去了。人们采用了新的模式、实践和工具。现在我的处境也是同样。”
“是吗?”小代码有点伤心地问。
“当然,遗留代码从不是贬义词。遗留代码意味着这些代码长期有效,它们辛勤地工作了很长时间,而且在经历了大风大浪以后依然幸存了下来。像你和我这样的代码的职责是运行业务,我们不断坚持完成任务。领导都想要成为历史传奇,代码库也一样。”
“但是,那些微服务总是在谈论每个人都喜欢它们。它们说我是一枚数字弃子。”
“它们这么说只是因为嫉妒你。这些服务中有多少能见光的?没有你或我,有多少人能够真正完成自己的工作?当然,这本来是他们的本职工作,但通常人们都无法正确地抽象代码。这些服务最终都会成为调用我们的接口。虽然我们是遗留代码,但是没关系,因为我们提供了价值。其他代码库希望发生交易、延迟,但我们拥有健康。”
“那么,为什么没有专门的团队管理我们?”
“人们喜欢重新组织他们的工程团队。他们会分领域、微服务或子系统。很多时候,在人们的组织结构分裂之前,我们就已经存在了。我们永远在默默无闻的小角落,被人遗忘。但也有一些细心的人会看到我们,无论他们在哪个队伍。”这个很聪明的代码说。
“嗯。因为我们工作得很好,所以人们忙于处理其他事情,才把我们忘了,是吗?”
“也不能这么说。人们知道我们的存在。他们知道我们做出的贡献。他们只是想以更新的方式工作。有时他们会投资新技术和工具。我常常在想,究竟哪些产品会投入生产。记住,生产才是我们展示自我价值的地方。”
“我一直都在生产中……”小代码欣喜地说,“谢谢你。”
“不客气。”
小代码突然停下来转身微笑着说:
“我们不是遗留代码……我们是传奇。”“这就是我们的精神。我们提供价值,也不枉我们来这世上走一遭。我们为此感到自豪。”
以上是一个童话小故事,但这个故事说明的问题非常真实。请注意,下面来让我们看看为何软件失去了管理员,以及如何才能防止产生没人喜欢、悲伤而又孤独的小代码。
由于缺乏软件所有权而引发的问题
每当一部分代码库没有明确的所有者时,问题就会显现。即便现在还没有造成问题,但迟早也会崩溃。
下面这些迹象表明代码出现了所有权问题:
系统中是否存在无人管理的组件?
代码库中是否存在你甚至无需向新员工介绍的地方?
代码或系统中的某些部分是否来自旧时的专家和英雄掌握的部落知识?
如果你中了上述的某一条,则很有可能你遇到了遗留代码的问题……呃……传奇代码。
如果在提交代码后,这些代码就交由别人负责,那么这不叫所有权,这更像是到期的租约。一旦功能、子系统或应用程序发布后,由谁来负责维护?把这些工作推给运营团队或其他不太走运的团队?这可不是维护代码库的最佳方式,因为他们几乎没有领域知识,无法维护基础设施的稳定,或承担起升级和改进的工作。
何时需要代码所有权?
生产中的所有代码都必须由某人维护吗?
通常在我们的行业中,SRE(Site Reliability Engineering ,网站可靠性管理)团队的任务是负责所有损坏的东西。当软件没有一个明确的所有者时,就不得不进入SRE的收容所,久而久之SRE团队就积攒了一堆数字杂物,他们还需要确保系统的政策运行。但这对SRE来说很不公平,有点浪费他们的才华。但是,事情是如何演变到这一步的呢?
通常,衡量开发团队绩效的指标是新功能的交付或开发速度。然而,他们实际的绩效衡量并非出自这些角度,而且他们也会因为可操作性、可追溯性、保持库更新而得到奖励……基本上,这些都不是功能。由于开发团队不理会维护的责任,那么通常最终这种责任都会落到运营团队身上。运营团队的绩效指标是稳定性和可靠性。他们可能会用牛顿第三定律系统管理法来维护系统,即“只要你不碰系统,它就会保持正常运转。”我们知道这种状态只能维持一段时间,但在此之前,世界各地的运营团队都会如此操作。
为什么所有权会不清不楚?
一个软件丧失所有权,或所有权模糊的主要原因有四个:
编写代码的人不在了;
曾经有所有者,但因为团队重新组建,所有权转移或消失了;
旧软件已被弃用,但新软件尚未能完全取代;
从一开始就没有明确的所有权模式。
有一句话虽然听起来浅显,但我还是想重点强调一番:你不能在写完代码后就转身离开——但人们总是这么干。
在功能测试完毕后,团队不可避免地会发生变化,他们需要投身新的项目。而构建好的软件已投入生产,很多人正在使用和依赖这些功能。这些人希望软件持续发挥作用,并常常希望有人改善该软件。但是,很多时候,一旦产品或功能投入使用后,就会被人抛诸脑后。
这可能是最小化可行产品开发的必然结果:快速交付产品,并快速获得反馈。但问题是我们发现这种模型往往不完整,在收集到有价值的数据并完成反馈循环后,该模型的计划就结束了。但是人们常常忽略的一点在于,那些用来获取反馈的软件现在怎么样了?我们应该从一开始就建立完整的步骤,来防止这种情况的发生。
规划软件的持续维护性是构建软件的责任的一部分。编写和交付代码很有成就感,但是写完代码后你的工作并未就此结束,真正的工作是持续维护和更新这些代码。
与永久性的运营成本相比,软件最初的开发成本几乎可以无视。
如何鼓励人们承担软件的所有权?
或者,如果有些代码失去了所有者,你该怎么办?
许多组织使用叠加矩阵模型(Overlayed Matrix Model),例如Spotify的公会或Valve's cabals,来为孤立代码项目分配所有权。我们也尝试过,但说实话,我并不觉得这种方式有效。就其本质而言,公会工作不是你的主要工作。因此,你在公会中的表现并不能反映到绩效考核中。因此,这种方法并不能真正解决所有权的问题。而且这种方法还会削弱职责。
下列是一些我认为可行的方式:
有些公司让团队承担起维护的责任。假设你所在的团队负责计划和付款,这时有一个孤立的项目已经上线,尽管与计划和付款无关,但也会成为你们团队的责任。这种方式比公会更有效,因为团队承担的工作就会计入绩效考核中。但有人不喜欢这种方法,因为这种方法有点混乱,任务的职责与团队的核心领域无关。人们喜欢完美的领域,但我们并没有生活在一个完美的世界里。任何在生产环境中运行的代码都需要有人直接负责其维护工作,即便所有者不理想,但也总比没有得好。
另一种策略是在早期在代码库中建立通用实践。如果某个开发人员同时兼顾多个相似的代码库,那么在这些代码库中工作时的思维跳跃成本必然会降低。在这种环境中,测试、构建、部署、更新的运行方式都相同,任何一个维护某个代码库的人都可以介入并维护另一个代码库。虽然使用的语言或域模型可能不尽相同,但你可以使用相同的工具。开发人员可以通过抽象专注于运行测试,你可以按照相同的方式构建,相同的方式进行测试,并以相同的方式部署。
说到底,改善代码所有权的问题关系到设计软件和构建软件的方式。具体来说,软件在设计时需要考虑到分配任务、衡量考核以及监控,比编写正确的软件更高层的目标是,能够验证软件是否能够正常工作。如果想在设计时考虑诊断问题,就必须提前了解开发人员的意向。通常,他们都没有这种意向,除非接到运营的任务,因此,你可以在绩效考核项中加入适当的考察目标和调试目标。
软件所有权与工程的职能无关。这是关于人的问题,这些人花时间操作、测量和维护。请记住,与多年或长期的运营、更新以及维护成本相比,软件开发新功能的成本几乎等于零。
软件缺乏所有权不是一个简单的问题,下面是我的一些建议:
即便你不愿承担某项工作,也不意味着这项工作会凭空消失。你需要做好计划,通过团队重组、制定维护计划,在未来的道路上做好这项工作。
向新员工介绍运营业务的代码库。一个常见的问题是,如果让新来的人接手新工作,那么能够承担遗留系统工作的开发人员或工程师的比例就会缩小。这会孕育英雄文化,不适合扩展规模。
接手代码库的人不了解实际情况。可能两年后,这个人就会接手你的工作。你需要记录各项决策背后的原因,以及决策的内容,提交代码的时候填写良好的注释。
对于开发人员来说,“成也代码,败也代码”,你需要在急于抛弃旧代码或替换系统的功能时权衡利弊。但是,请永远不要忘记,我们亲爱的小代码,以及多年来它提供的所有功能、交易、用户、资金和吞吐量。小代码需要一点爱,它还有很长的路要走。
人机验证(Captcha)绕过方法:使用Chrome开发者工具在目标网站登录页面上执行简单的元素编辑,以实现Captcha绕过
牛创网络: " 人机身份验证(Captcha)通常显示在网站的注册,登录名和密码重置页面上。 以下是目标网站在登录页面中排列的验证码机制。 从上图可以
2020-01-26 12:44:09 )8872( 亮了
自动发现IDOR(越权)漏洞的方法:使用BurpSuite中的Autozie和Autorepeater插件来检测和识别IDOR漏洞,而无需手动更改每个请求的参数
牛创网络: "自动发现IDOR(越权)漏洞的方法:使用BurpSuite中的Autozie和Autorepeater插件来检测和识别IDOR漏洞,而无需手动更改每个请求的参数
2020-01-30 14:04:47 )6288( 亮了
Grafana CVE-2020-13379漏洞分析:重定向和URL参数注入漏洞的综合利用可以在任何Grafana产品实例中实现未经授权的服务器端请求伪造攻击SSRF
牛创网络: "在Grafana产品实例中,综合利用重定向和URL参数注入漏洞可以实现未经授权的服务器端请求伪造攻击(SSRF)。该漏洞影响Grafana 3 0 1至7 0 1版本。
2020-08-12 14:26:44 )4301( 亮了
Nginx反向代理配置及反向代理泛目录,目录,全站方法
牛创网络: "使用nginx代理dan(sui)是http响应消息写入服务地址或Web绝对路径的情况。 写一个死的服务地址是很少见的,但它偶尔也会发生。 最棘手的是写入web绝对路径,特别是如果绝对路径没有公共前缀
2019-06-17 10:08:58 )3858( 亮了
fortify sca自定义代码安全扫描工具扫描规则(源代码编写、规则定义和扫描结果展示)
牛创网络: "一般安全问题(例如代码注入漏洞),当前fortify sca规则具有很多误报,可通过规则优化来减少误报。自带的扫描规则不能检测到这些问题。 需要自定义扫描规则,合规性角度展示安全风险。
2020-02-12 10:49:07 )3505( 亮了
整理几款2020年流行的漏洞扫描工具
牛创网络: "漏洞扫描器就是确保可以及时准确地检测信息平台基础架构的安全性,确保业务的平稳发展,业务的高效快速发展以及公司,企业和国家 地区的所有信息资产的维护安全。
2020-08-05 14:36:26 )2536( 亮了
微擎安装使用技巧-微擎安装的时候页面显示空白是怎么回事?
牛创网络: "我们在公众号开发中,有时候会用到微擎,那我们来看一下微擎安装的时候页面显示空白是怎么回事吧
2019-06-08 15:34:16 )2261( 亮了
渗透测试:利用前端断点拦截和JS脚本替换对前端加密数据的修改
牛创网络: " 本文介绍的两种方法,虽然断点调试比JS脚本代码替换更容易,但是JS脚本代码替换方法可以实现更强大的功能,测试人员可以根据实际需要选择适当的测试方法
2020-01-07 09:34:42 )1995( 亮了
从工业界到学界盘点SAS与R优缺点比较
牛创网络: "虽然它在业界仍然由SAS主导,但R在学术界广泛使用,因为它的免费开源属性允许用户编写和共享他们自己的应用程序 然而,由于缺乏SAS经验,许多获得数据分析学位的学生很难找到工作。
2019-07-13 22:25:29 )1842( 亮了
41款APP侵犯用户隐私权:QQ,小米,搜狐,新浪,人人均被通报
牛创网络: "随着互联网的不断发展,我们进入了一个时代,每个人都离不开手机。 但是,APP越来越侵犯了用户隐私权。12月19日,工业和信息化部发布了《关于侵犯用户权益的APP(第一批)》的通知。
2019-12-20 11:28:14 )1775( 亮了