代码恐怖故事:隐藏在复杂代码库中的恐怖秘密

48d2a106efe9c5ab17b6b36564b08d8b.gif

本文讲述了开发者们在复杂代码库中工作的经历和教训,包括代码复杂性带来的问题、架构决策、第三方库引发的意外问题以及令人恐慌的编程错误,以及如何处理这些挑战。

原文链接:https://digma.ai/blog/coding-horrors-tales-of-codebase-complexity/

未经允许,禁止转载!

作者 | Daniel Beck       译者 | 明明如月

责编 | 夏萌

出品 | CSDN(ID:CSDNnews)

1e22499d176a1d07987334c24233e890.png

无论你是软件开发领域的老兵,或者刚刚踏上这个领域的新人,你可能都对在复杂的分布式软件环境中工作所带来的压力和那些让人瞠目结舌的惊魂时刻有着深深的认识。我们深信,你一定曾面临过代码库复杂性所引发的问题,也在调试的过程中历尽艰辛,或者因为错误的设计决策而有过自己的“代码恐怖故事”。

毕竟,许多开发者都有类似的故事可以分享。我们决定每次邀请一位知名的开发者,分享他们的代码恐怖故事。这一次,我们请来了 Daniel Beck——一位拥有丰富软件开发经验的专家、产品开发的用户体验顾问,由他和我们分享他的代码恐怖故事。

Daniel 在软件开发领域的经验相当丰富!他从业的时间甚至可以追溯到该行业的早期阶段。他开始工作时使用的浏览器还是 NCSA Mosaic。在那个时代,只需要掌握五个 HTML 标签,你就可以开始投入工作了。在他的职业生涯中,Daniel 积累了独特的见解,我们坚信你们可以从中受益。

大家如果感兴趣可以访问他的博客,大家的访问能给他带来更大的创作动力!danielbeck.net/blog

18014f7fccc1c32d14e8552973c5d2d2.png

处理代码库的复杂性:教训和建议

  • 直观且易读的代码,无论其是否精巧,都优于那些晦涩难解的“聪明”代码。

  • 不应轻易接受厂商将问题归咎于硬件并推荐高价的服务器升级。

  • 认识到快速解决问题可能带来的隐患,理解代码底层工作原理的重要性。

  • 开启和关闭数据库连接是一个缓慢且开销大的操作。

  • 在安装新的 npm 模块或引入他人的代码时,必须深入考虑其潜在的风险和影响。

  • 警惕那些基于个人审美重构代码,却没有提供适当文档或确保代码完整性的团队成员。

  • 确保对代码的更改有充分的文档记录。

  • 对于那些进行无文档变更,为他人设置隐蔽陷阱的同事,应保持警惕。

  • 优化代码审查流程,以解决现有的问题。

  • 要认识到即使像 Facebook 这样的大公司也会犯错误,以免过分迷信他们,比如他们在 2021 年10月4日的 DNS 故障。

  • 避免在生产环境中由于不小心而导致的破坏。

  • 有 BUG 的代码总是可以修复的,而人的关系,那就要复杂得多,需要更加谨慎对待。

47da1417ec6fbd8a59fee93d8f837dc6.png

关于代码库复杂性,你是否有过令人惊恐的糟糕经历?

是什么引发了这场恶梦?

Daniel:这个问题真的只有在回首过去的时候才显得恐怖;当时,我倒是自认为这是我最得意的一次创作。(没错,这是我自己犯下的错误。)

这个项目的目标是设计一个内容管理系统,用于批量生成特殊类型的网站变体。我负责搭建前端系统,输入网站数据,通过一系列精心设计的模板,生成最终的网站。

那是在 20 世纪 90 年代末,那时整个行业都认为 XML 是行业标准,应当遵循。因此,我理所当然地决定使用 XSLT 来构建模板系统。

如果你对 XSLT 不熟悉,它是一种非常纯净的语言,用于将 XML 结构转换为其他 XML 结构,因为 XML 被认为是标准,所以 XSLT 也是用 XML 编写的。

其中一些有趣的挑战包括:XSLT 是严格的幂等的,从哲学的角度来看,这是很好的,但从实践的角度来看,这意味着所有的循环操作都必须通过递归完成,因为增加一个用于迭代循环的变量会被视为一个副作用,因此是不允许的。流程控制最好通过数据的分解而不是分支逻辑来完成。对于习惯了脚本语言和标记的人来说,这真的是一个大挑战。

我却很喜欢它。我不再需要从后端的团队那里获取我需要的具体数据,所有的数据都会以一个巨大的 XML 块的形式传给我,我可以通过我日渐庞大的 XSL 模板块生成我想要的任何东西。我觉得我有了超能力!我可以做任何事情!

现在,需要明确的是,整个过程我都乐在其中,我完全清楚我正在使用的是一门注定要失败的语言。这是在现代前端框架诞生之前很久的事情了,那个时候,“前端”技能通常意味着你熟悉 Photoshop、HTML、CSS,以及可能从其他网站“查看源代码”功能获取的一小部分 JavaScript 代码。相比之下,这里有一种非常复杂,看起来很奇怪的“前端”语言,它需要一些比当时的网络开发者所习惯的计算机科学概念更为高级。

但我却很喜欢它,而且正在学习这些高级概念,并因为能做到这一点而。在大约一年的时间里,我构建了一个相当大的模板集,随着我对我正在做的事情的理解逐渐深入,它们变得越来越不那么糟糕。到最后,我在编写高度解耦的,符合最佳实践的代码,我觉得它们聪明,甚至有时候会觉得有些“优雅”。我按照计划发布了产品,收取了我的合同费用,然后带着满满的信心投入到了下一份工作。

我得到的消息是,在接下来的五年里,他们一直没对这些 XSL 模板做过维护,直到产品被全部淘汰并替换,因为在公司里真的没有其他人能理解它们是如何运行的。显然,那些我自认为聪明、优雅的代码是多么糟糕。我的早期,简单直接的代码反而更易于理解和维护。

这是一个重要的教训。直观、易读的代码,无论其是否精巧,都优于那些聪明且复杂的代码

8a26d648d181647c4fd0dc0aab8c9ec7.png

请描述一个在项目中遇到的可怕的架构决策。

您是如何处理的?

这是我作为自由职业开发者的岁月中的一次经历。一家经常将大部分开发工作外包的中等规模公司,也是我的长期客户,有些惶恐地找到我:他们将一个小型项目托付给了一个新的供应商,工作已经接近尾声,即将达到上线的时刻。然而,一旦他们开始使用实际数据替代测试数据,他们便开始遇到严重的性能问题:当网站需要处理超出小数据量时,整个网站就会显著地变慢。供应商将问题归因于硬件,并建议升级到更强大、更昂贵的服务器。在掏出这笔钱之前,客户让我来对此进行实地考察。

长话短说,问题最后被定位到是供应商编写的一个函数导致的,这个函数使得他们与数据库的交互变得更加便捷:你只需要将 SQL 查询语句输入给它,它会打开数据库连接,执行查询,返回结果,然后清理并关闭连接。

这的确使他们的代码非常易读。然而,问题在于——我相信许多读者可能已经意识到——开启和关闭数据库连接是一个缓慢且耗资源的过程。理想情况下,你应当在开始时打开一次,执行所有查询,然后在全部完成后再关闭。但是,由于这些人的编程方式是对每一个独立的操作都开启和关闭连接,这就意味着有时需要打开和关闭数百次甚至数千次:一次是为了加载数据列表,然后每一项列表数据都需要再次开启和关闭。难怪服务器会变得如此慢!

最后,问题得到了简单的解决——只需将 'open' 和 'close' 操作从实用程序中移除,将它们移到程序的起始和终止部分,而非在循环中重复执行。然而,这是一个极好的例证,展示了快捷方式的潜在危险,以及使事情运行起来和理解为何它能运行以及它在后台做了什么之间的差别。如果他们每次开启和关闭数据库都必须编写代码,他们可能就不会遇到这个问题了,但事实却是,这个操作被隐藏在辅助函数里,所以人们很容易忽略。

我每次安装一个新的 npm 模块或者以其他方式引入别人的代码时,都会想起这个故事……这个模块在做什么看似合理的事情,有可能会给我的工作带来困扰吗?

6cf7bd44ab0b54cfa86004852a13fe8b.png

重构之殇——如何走向失败?

我们拥有两个独立却相关的网络产品,由各自的团队分别使用不同的编程风格在各自的代码库中进行开发。我们的目标是将这两者整合成一个产品。

由于两个代码库的复杂性和庞大规模,要将它们重构成一个整洁、统一的代码库无疑是一个长期的项目;与此同时,我们急需一个短期的解决方案。

我们原本应该保持原有的代码不变,只需在统一的用户界面上添加各个产品间的导航链接。

然而,我们实际上做的是将产品 A 的所有代码复制到产品 B 的代码库的子目录中,希望能够逐步重构两个产品的代码,使之互相匹配,并在此过程中找出并消除重复功能。

这个方法可能会取得好的结果!然而,一个事实打破了这种可能性,那就是那位负责复制代码的工程师认为在此过程中进行部分重构是个好主意。他根据自己的编程风格,对两边的代码进行了大量的重大改动,完成程度各不相同。

在这个过程中,他大部分时间都在设法避免对代码产生明显的破坏,然而他同事们并不知道他已经做了一些未记录的改动,这些改动也留下了难以察觉的陷阱。然后,他立即辞职,加入了一家竞争公司。

此事件确实反映了该组织在管理和代码审查流程方面的重大缺陷。

所以,我们最终以原本预计的两倍时间投入完成了那个艰难的重构,同时也进行了代码审查。我们最终完成了,但整个过程非常痛苦,是我至今为止最令人后悔的一次经历之一。

最后我听说,那家公司正在“拆分单体应用”,并开始将那个统一的前端分解为独立却相关的产品

59c0990052af39cfe83979b7028273ae.png

你是否曾被第三方库或框架带来的意料之外问题或复杂性困扰?

在 2021 年 10 月 4 日,Facebook 因 DNS 故障导致自身以及其相关 API 大部分时间不可用。这也使得我们的应用程序由于过度依赖这些 Facebook 的 API(我们默认它们永远在线)而被迫下线。毕竟,这是我们都信任的 Facebook,没人会预料到 Facebook 的服务会出现这样的问题。

为了修复这个问题,我们紧急进行了大量代码重写。然而,就在我们几乎完成部署并让应用程序在没有那个 API 的情况下也可以正常运行的瞬间,他们的 API 服务恢复了。

好吧,至少我们为下次问题做好了准备

5d2c5049cd3156352a24b38932775f33.png

你是否经历过令人恐慌的惊魂时刻,

或者犯了令你心惊胆战的编程错误?

我一直严格确保自己不去访问生产服务器,因为我不想成为那个无意间在生产环境中破坏某些东西的人。

然而,我还是犯了错误:“这里还有一些未合并的代码,让我登录服务器来处理一下。”结果造成了意外!那天在 Slack 上的情况,我都截图保存了下来:

0ddb41f17e881e14389197de7c9af849.png

但这还只是代码问题,代码问题比较好解决,人就难搞定了。

我职业生涯中真正的恐怖瞬间,则要追溯到 Slack 和 Hipchat 之前,回到电子邮件的时代。

那是在一家小而成熟的初创公司。我们的一位客户支持人员在深夜向团队的一部分人发送了一条消息,寻求处理一个特别苛刻的客户问题的建议。我已经不记得具体的问题是什么了,但那个问题演变成了一场工作时间之外的抱怨会,我们大家都在电子邮件中抱怨这些客户多么难以应对,他们的一些要求多么不合理。名单越来越长,从销售到工程到首席执行官,每个人都对此进行了抨击。最后,客服代表得到了她需要的答案,并将其发送给了客户。

然后这个消息回到了列表中:“呃...伙计们?我想我可能不小心把整个电子邮件线程都转发给了客户。”

接下来的十分钟内,所有人都陷入了沉默,心跳加速地翻阅整个回复链,寻找自己可能需要道歉的言论。最后结果证明是虚惊一场,她实际上并没有将整个电子邮件线程发送给客户。但那确实是一个我希望再也不要经历的惊魂时刻。有 BUG 的代码很容易修复,但人的关系破坏了就很难修复了。

本文是“代码恐怖故事”系列第二篇,第一篇《代码恐怖故事:揭秘形成复杂代码库的常见原因》欢迎大家回顾。

大多数开发者都有自己独特的故事。你是否也曾亲历过一些“代码恐怖故事”?欢迎在留言区分享讨论。

推荐阅读:

▶Mac 上能跑国产系统了!深度 deepin 官宣:正式适配 M1 芯片

▶代码恐怖故事:揭秘形成复杂代码库的常见原因

▶突发!ChatGPT 紧急暂停 Bing 集成,下线搜索功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/30424.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【ChatGPT助我开发】利用ChatGPT编写基于Matlab的SVM的蔬菜分类项目

序言 从去年12月份开始用ChatGPT,一直被惊艳到,然后问一些奇怪的问题,到现在助力开发,我发现合适的提示词(Prompt)会很大程度影响到生成的质量,我在开发的过程中也会逐渐完善修改,最…

matlab绘图常用函数及代码

1、绘图:plot /semilogy /loglog /scatter figure(1); subplot(1,2,1);%子图 axis([0 10 10^-5 10^-1]);%限制作图范围,x轴0~10,y轴10^-5到10^-1 plot(X,Y,Color,[R G B],LineStyle,-,Marker,o,LineWidth,1); hold on; grid on;%显示网格 &…

HR怀疑程序员简历造假,随后的做法引起网友热议:过分了

简历可以说是求职过程中最重要的一份材料,因此不少人对简历都精心准备,以便全面地展示自己。对企业来说,简历最重要的一点便是真实。可以说所有公司对简历造假都是保持零容忍的态度。最近,一位HR网友在职场社区分享了他怀疑程序员…

程序员简历优化之道

作者:安晓辉 声明:原创文章,禁止各种形式的转载。 为什么你投十份简历,只有一两家公司约你?又或者为什么你每投一份简历都能获得面试机会? 最根本的原因,就是一方在汲汲渴求,而恰恰…

别再胡乱写简历了,一份适合普通大众的简历模版,送给大家

今天我们就来聊一聊在校招时,简历该如何写的问题。说实话,对于简历的书写方式,可能不同的人会有不同的见解,并且不同的面试官/HR在筛选的时候也会有所差异,所以在我看来,不存在一种绝对稳的简历模版。 我在…

聊求职:写简历的大原则与小技巧

简历,是求职者向未来雇主展示专业技能和职业素养的自我推销工具,是赢得面试机会的敲门砖。如果没有面试邀约,大多只有两种可能:要么是简历写的太屎了,要么是简历投的太屎了。所以,当没有面试机会的时候&…

用 Markdown 写炫酷简历,助力跳槽换工作

大家好我是徐小夕。 今天给大家来介绍一个简历制作神器,是我的朋友秋风开发的。这个项目是一款免费在线简历制作工具,通过将书写的Markdown 和选择的主题快速转化不同风格的简历, 同时还可以一键复用其他人做的优秀的简历, 助力求职者快速制作精美的简历…

分享162个助理类简历模板,总有一款适合您

分享1626个助理类简历模板,总有一款适合您 162个助理类简历模板下载链接:https://pan.baidu.com/s/1Uy3eXPz9D-wK-l7z3KDIWQ?pwdl139 提取码:l139 Python采集代码下载链接:采集代码.zip - 蓝奏云 class ChinaZJsSelenium:ba…

掌握这些写简历投简历的“黑魔法”,告别简历已读不回!

“哎,我还能找到工作吗?” 这是最近加我微信的好友,问的最多的一句话。 太卷了 最近加我微信的朋友很多,我都很奇怪,最近也没怎么发文章,怎么会有这么多人加我。 大概就是因为太卷了,之前写的…

简历优化实战案例01:工作经历篇

大家好,我是小谭。 最近,我在帮一位求职者修改简历时,发现一些求职者常犯的简历错误。在征得求职者同意后,我粘出来,同大家分享和交流,期望通过此分享,让大家了解写简历的常见坑和注意点。 本…

分享111个助理类简历模板,总有一款适合您

分享111个助理类简历模板,总有一款适合您 111个助理类简历模板下载链接:https://pan.baidu.com/s/1JafYuLPQMmq37K4V0wiqWA?pwd8y54 提取码:8y54 Python采集代码下载链接:https://wwgn.lanzoul.com/iKGwb0kye3wj 设计师助理…

找工作的程序员应该这样优化简历【内附120套优质简历模板】

《花千骨》一剧,白子画为什么收花千骨为徒? 《琅琊榜》中,梅长苏为什么选靖王而弃太子、誉王? 《泰坦尼克号》里,杰克和露丝为什么会一见钟情? 王子基特为什么会选择灰姑娘辛德瑞拉? 这些问题乍…

易语言易语言浏览器html5,易语言创建的浏览器源码

易语言创建的浏览器源码系统结构:事件_编辑框1_获得焦点,事件_选择夹1_鼠标右键按下,子程序_删除页面,事件_窗口1_尺寸被改变,事件_选择夹1_子夹被改变,子程序_添加页面,事件_浏览器_即将跳转,事件_浏览器_即将打开新窗口3,事件_浏览器_标题被改变,事件_编辑框1_按下某键,SkinH…

易语言 普通填表 html5,易语言网页填表源码

易语言网页填表源码系统结构:passport_tianya,passport_xinlang,passport_baidu,Automatic_modification,Insert_text,Loadconfiguration, 窗口程序集1 || ||------_按钮8_被单击 || ||------_按钮11_被单击 || ||------passport_tianya || ||------passport_xinlang || ||----…

易语言启动局域网计算机程序,易语言局域网计算机监控源码

易语言局域网计算机监控源码系统结构:取计算机列表,弹出提示窗,上下线, 窗口程序集1 || ||------__启动窗口_创建完毕 || ||------取计算机列表 || ||------_选择框1_被单击 || ||------_时钟1_周期事件 || ||------_按钮1_被单击 || ||------_按钮2_被单击 || ||------__启动窗…

易语言在线播放器源码php,易语言视频播放器源代码

用简单的语言编写视频播放器的源代码 源代码包含以下功能: *调用Thunder APlayer SDK进行视频播放*自动检测是否下载Thunderbolt解码库,如果不存在,则自动下载并解压缩(新手可以学习)新手可以学习)*支持快捷键可快进和快退以及将音量最多增加或减小至1000 *自动截取本地视频缩…

易语言PHP自动更新,易语言自动更新源码

作为软件制作者,很多时候,我们都需要自动更新来约束软件使用者。尽管有些人不愿意更新,但是长久使用老版本毕竟不是长久之策。小编这里给大家带来易语言自动更新的源码模块,放入你的软件中正合适,需要的话就来试试吧&a…

易语言html截图,易语言窗口截图源码

易语言窗口截图源码系统结构:子程序1,PaintRect,SetTimer,GetCursorPos,WindowFromPoint,KillTimer,GetWindowRect,CreateDC,IsRectEmpty,PatBlt,DeleteDC,SetParent,GetParent, 窗口程序集1 || ||------__启动窗口_创建完毕 || ||------_图形按钮1_鼠标左键被按下 || ||------…

易语言 网页访问伪造ip

一、x-forwarded-for协议头 在精易网页助手的提交协议头加入 x-forwarded-for: ip地址最后生成的代码(部分): .版本 2ADD_协议头.添加 (“x-forwarded-for”, 参_ip, ) 局_提交协议头 = ADD_协议头.获取协议头数据 ()局_结果 &…

易语言拖拽文件获取文件路径

一. 易语言软件配置 1. 点击工具 2. 配置如下,点击确定 3. 二 . 创建窗口 1. 在左侧程序数据点击右键 选择创建窗口 2. 程序载入窗口 3. 然后启动程序就可以有有程序窗口了三. 添加组件 1.添加如下三个组件 拖放组件配置 接收文件选择真 2.注册拖放组件 3.注册成功之后 …