0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

你见过最糟糕的代码是什么?25,000,000 行的代码就问你敢不敢动?

电子工程师 来源:lq 2018-12-12 09:51 次阅读

你经历过绝望吗?近日,Hacker News 上发起了一个名为“你见过最糟糕的代码是什么?”(https://news.ycombinator.com/item?id=18442637)的话题,引发了无数网友回忆讨论,甚至还再次让软件巨头 Oracle 登上头条。

25,000,000 行的代码就问你敢不敢动?!

日前,我们还在说如今的 Oracle惨遭亚马逊、Salesforce 弃用,究其根本原因,不是因为亚马逊等企业为了省钱,而是因为 Oracle 数据库逐渐满足不了他们业务的发展需求。

在 Oracle 内部,相比每隔六个月就更新一次的 Java,Oracle 数据库版本的更新频率可以用 2-3 年甚至更久来表示。就在上文所述的Hacker News 话题中,来自 Oracle 的程序员为我们解释了其中的缘由,庞大的 Oracle 数据库并不像外人看得那么简单,修复 Bug 可以分分钟让人奔溃。

该程序员以Oracle 数据库 12.2 版本为例,它拥有了近2500 万行的 C 代码。

每次更新,你需要在不破坏现有测试 1000 次的情况下更改产品中的单行代码。就 Oracle 数据库产品而言,是好几代程序员在有限的期限内编写的这些代码,但与此同时,这些代码中也充斥着大量的垃圾代码。

非常复杂的逻辑、内存管理、上下文切换等都与数千个 flag 一起保存。整个代码都带有神秘的宏命令,如果没有使用笔记本而是手动扩展相关的宏,那么你就无法清楚地明白这些宏。甚至可能需要一天到两天才能真正理解某个宏的作用。

有时你需要了解 20 个不同 flag 的值和效果来预测代码在不同情况下的行为方式。有时多达数百个 flag!“我并不夸张。”该程序员表示道。

Oracle 这个产品仍然存活并且可以供企业和开发者使用的唯一原因是数百万次测试!

接下来,该程序员分享了 Oracle 数据库开发人员的日常:

- 开始处理一个新的 Bug。

- 花两周的时间试图了解 20 种不同的 flag,这些 flag 以神秘的方式相互作用,造成了这个困境。

- 再添加一个 flag 来处理新的特殊情况。添加几行代码来检查此 flag 并解决有问题的情况,避免该 Bug。

- 将更改提交到包含大约 100 到 200 台服务器的测试服务器集群,这些服务器将编译代码,构建新的 Oracle 数据库,并以分布式方式运行数百万个测试。

- 下班回家。第二天来上来,继续做其他事情。测试可能需要 20 小时到 30 小时才能完成。

- 一天结束,下班回家。再来上班时,检查前天的集成测试结果。如果幸运的话,将会大约有 100 个失败的测试。如果运气不好,将大约会有 1000 个失败的测试。随机选择一些测试并尝试了解你的假设出了什么问题。也许还有 10 多个 flag 要考虑才能真正理解 Bug 的本质。

- 添加一些 flag 来尝试解决问题。再次提交更改以进行测试。再等 20 到 30 个小时。

- 另外,重复以上步骤大概两周左右,直到你能得到将这些 flag 组合起来的“神秘咒语”(没有错误发生)。

- 终有一天,你会成功,带来测试失败为零的结果。

- 针对你新更改的部分添加 100 多个测试,以确保下一个不幸接触这段新代码的开发人员永远不会破坏你的修复程序。

- 完成最后一轮的测试提交工作。然后提交以供审核。审查本身可能还需要 2 周到 2 个月。所以现在继续讨论下一个 Bug。

- 在 2 周到 2 个月之后,当一切都完成后,代码将最终合并到主分支中。

以上是在 Oracle 修复 Bug 的程序员日常的非夸张描述。现在想象一下开发新功能会有多么恐怖。开发一个小功能需要 6 个月到一年(有时是两年!比如添加一种新的身份验证模式,比如支持 AD 身份验证),现在也可以理解为什么 Oracle 数据库的更新速度永远追不上 Java 了。

而对于这款产品可以商用也真的是一个奇迹。到了最后,这名程序员崩溃地说:我不再为 Oracle 工作了。永远不会再为 Oracle 工作了!

对于这一现状,更有不少网友表示了同情:

@nathan_f77:这绝对是疯了。 我甚至无法想象代码库的复杂性。我认为我的 Rails 测试套件已经很慢了,因为它需要 4 分钟。如果我用 C 或 C ++ 编写它可能是 10 秒。

我无法想象一个 C / C ++ 的应用程序,其中测试套件在具有 100-200 台服务器上需要 20-30 小时。如果你仅更改一次之后突破 100-1000 次测试,那么它就不像独立的模块化那样了。

测试运行间隔 30 小时! 我绝对不会接受这份工作, 因为光听起来,就像是地狱。

rm-rf 的怨念

那如果说在 2500 万行的代码上动刀,光是测试就已经如此复杂了,除了之外,是否还有比这更可怕的代码?

必须有!

让很多程序员后悔到想剁手的“rm -rf”绝对要算一个,糟糕的不是命令行本身,而是它带来的后果。此前,不仅有顺丰程序员的删库跑路事件,就连前MegaEase 创始人&CTO 陈浩(微博@左耳朵耗子)也未能逃脱该命令行带来的魔咒。

那年写 Unix Shell 脚本,本想删除一些临时的子目录,如:rm -rf ${mydir}/ ,结果呢,我没检查 ${mydir} 这个变量是否为空,于是呢,在某种情况下,这变量真的为空了,于是,我成了团队的千古罪人。

那些年,我们见过和创造的“渣渣”代码

论起是否遇到过糟糕的代码时,天下的程序员似乎有着极高的相似性,在此,更有知乎网友(https://www.zhihu.com/question/30776912)吐槽:

@小猪:

if (b == true) {...}

我不常写 C,不知道 C 程序员是不是觉得这种写法是理所当然的,但当我在 Java 代码中频繁的看到这种代码的时候,我真的很无力。

@周越:

(a != b) ? b : a

@侯杰:

enumFiveLine{Gold,Wood,Water,Fire,Earth,};

看枚举名字不知道五行(hang)是什么鬼,看了枚举内容恍然大雾,原来是五行(xing)……

@玻璃杯中的鱼:

// 以下所有left代表右

// 以下所有right代表左

写在最后

在程序员的日常生活中,面对参差不齐的代码,Debug 成功了叫创新,改 Bug 失败叫掉坑,但是,如今的大牛哪一个又不是在写 Bug 与Debug 中博弈过来的呢,也正是有了这些糟糕的代码才能让彼时的菜鸟们真正得以历练,而对于历练过程中需要注意什么,对此,CSDN 也曾发文从代码的基本规范和约束、编程思想、版本迭代与重构、设计模式等角度,为大家一一讲清如何才能成长为优雅的大牛程序员。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据库
    +关注

    关注

    7

    文章

    3716

    浏览量

    64052
  • 代码
    +关注

    关注

    30

    文章

    4674

    浏览量

    67820
  • Oracle
    +关注

    关注

    2

    文章

    282

    浏览量

    35055

原文标题:25,000,000行的代码就问你敢不敢动?!

文章出处:【微信号:rgznai100,微信公众号:rgznai100】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    NONOS_SDK 1.5.4.1导致致命错误的补丁怎么处理?

    从 1.5.4 代码库返回对应用程序二进制文件进行编程,我的应用程序将正常启动。 见过类似的问题吗?
    发表于 07-11 07:57

    STM32CUBE ETH->DMABMR一直不为0x000的可能原因是什么呢?

    用的F407+rtl8201F芯片(网口芯片又晶振输入25M) 调用官方库文件一直卡在下方代码这,ETH->DMABMR一直不为0x000 while
    发表于 05-20 06:06

    贾扬清的500代码,掀翻了Perplexity5.2亿的桌子?

    500代码VS估值5亿1月25日,自从宣布创业后就备受社区瞩目的贾扬清,在推特上展示了一个对话式搜索引擎的demo。这个demo基于他创办的LeptonAI提供的框架,“只用500
    的头像 发表于 04-17 08:05 128次阅读
    贾扬清的500<b class='flag-5'>行</b><b class='flag-5'>代码</b>,掀翻了Perplexity5.2亿的桌子?

    怎么给stm8s000f3烧录.bin文件?

    求助,怎么给stm8s000f3烧录.bin文件?谢谢!手里有stlink-v3set
    发表于 04-10 06:48

    g代码和m代码表示什么功能

    G代码和M代码是数控机床程序中常用的两种指令代码,用于控制数控机床的工作动作和运动方式。 G代码是指控制机床工作动作的指令代码,它是一种简单
    的头像 发表于 02-14 15:49 3327次阅读

    tle9877刷写codeflash(0x11000000-0x1100f000)后,flash刷写失败且中断停止响应怎么解决?

    当前问题:在用户代码运行期间,尝试刷写codeflash(0x11000000-0x1100f000)后,flash刷写失败且中断停止响应。 请问能否直接刷写codeflash?可以的话,应怎么操作?
    发表于 01-31 08:28

    ad7656串输出代码

    ad7656串输出代码是一段常见的嵌入式系统开发代码,用于控制外部设备进行串行通信。本文将详细介绍该代码的功能、结构、使用方法以及注意事项。 首先,了解ad7656是什么。 AD76
    的头像 发表于 12-28 10:38 697次阅读

    keil中的代码格式化插件Astyle介绍

    在keil中一的缩进自己的代码,虽然注重代码的格式是一个好的习惯,不过这样代码比较多的话,整理起来效率太低,推荐Astyle这个工具,
    的头像 发表于 11-28 12:29 2878次阅读
    keil中的<b class='flag-5'>代码</b>格式化插件Astyle介绍

    python代码写完后点哪个运行

    当你完成了编写Python代码后,可以选择多种方式来运行它。下面是几种常见的运行代码的方式: Python解释器:Python是一种解释型语言,可以直接使用Python解释器来运行
    的头像 发表于 11-24 09:28 3122次阅读

    python如何换行而不运行代码

    在Python中,换行是一种用来增加代码的可读性和组织性的方式。当你在编写Python代码时,换行通常用于分隔不同的代码或块,使其更易于阅读和理解。然而,并非所有的换行都会运行
    的头像 发表于 11-22 10:52 2099次阅读

    c语言怎么把代码全部注释掉

    要将C语言代码全部注释掉,即不让代码被编译和执行,可以使用注释语句来实现。C语言提供两种注释方式:单行注释和多行注释。 单行注释:使用双斜杠(//)来注释一代码。 示例: // 这是
    的头像 发表于 11-22 10:21 5260次阅读

    linux虚拟机怎么运行代码

    运行代码是Linux虚拟机中的常见操作,本文将详细介绍如何运行代码。 首先,要运行代码需要先安装好Linux虚拟机,并确保能够顺利运行。接下来,
    的头像 发表于 11-17 10:12 4070次阅读

    如何知道代码是否线程安全

    的?如何知道代码是否线程安全?要如何访问数据才能保证数据的安全? 本篇文章会一一回答的问题。 1. 线程不安全是怎样的? 要搞清楚什么是线程安全,就要先了解线程不安全是什么样的。 比如下面这段
    的头像 发表于 11-01 11:42 568次阅读
    如何知道<b class='flag-5'>你</b>的<b class='flag-5'>代码</b>是否线程安全

    社区代码贡献企业启新篇,深开鸿代码贡献量超过200万

    ,社区代码贡献企业取得新成绩,深开鸿成为华为之后,第二家社区代码贡献量超过百万行的生态企业、且总贡献量累计突破200万,为培育和发展OpenHarmony社区注入源动力!截至目前,华为代码
    的头像 发表于 10-18 16:15 582次阅读

    静态代码块、构造代码块、构造函数及普通代码块的执行顺序

    在Java中,静态代码块、构造代码块、构造函数、普通代码块的执行顺序是一个笔试的考点,通过这篇文章希望大家能彻底了解它们之间的执行顺序。 1、静态代码块 ①、格式 在java类中(方法
    的头像 发表于 10-09 15:40 1019次阅读
    静态<b class='flag-5'>代码</b>块、构造<b class='flag-5'>代码</b>块、构造函数及普通<b class='flag-5'>代码</b>块的执行顺序