你目前写过最大的bug

简介: 你目前写过最大的bug


前几天在知乎上看到《你目前写出的最大的Bug是怎样的》这个问答(点阅读原文可以看看)还挺有意思的,作为程序员,写出bug几乎是不可避免的,无非是造成的严重性和bug的程度不同(高级bug、低级bug),简单来聊下我自己在这块的印象。

常见的造成故障的问题


就我自己来说,之前写的东西造成过不少次挺严重的故障,但可能因为都发生在公司业务还没那么大影响力的时候,所以造成的故障的影响面相对还好,就会显得没那么严重,不过这么些年,眼见和处理过不少故障,写几个自己有印象的故障类型,多数严重故障其实也并不是什么很复杂的原因造成的,只是业务本身的影响力不太一样而已....

  1. 常见的自增长集合对象造成的内存溢出
    很多的语言里的集合类型的数据结构都是自增长的,看到过太多次,由于bug或业务增长,造成集合大小远超当时写代码时候的想象,最终造成内存溢出的问题。
    我建议是只要是动态的集合对象,都要给个大小的限制,避免未知的情况出现导致问题,所以一直希望语言本身能支持好,否则在并发类型的场景要专门处理下这个事情也挺折腾的。

  2. 常见的线程池误用造成的问题
    对于并发场景而言,线程池是经常会要用到的,语言层面通常会给些更易用的API,但这些里面通常要么等待队列是不限长度的,要么是线程池大小其实是不限的,最终也很容易造成类似上面自增长集合对象的问题。
    和1的问题一样,对资源的使用我建议是要有边界控制的,对一些在边界超出会导致进程退出的,其实在集群类的场景可能还好点,但例如对于Java,内存用多了没造成进程退出,但造成了频繁的GC,最终出现业务响应慢这种更严重的问题。

  3. 常见的批量API未限制造成的问题
    代码里通常会提供一些用来做批量操作的API,但其实通常并不会希望这个批量操作是没边界的,例如可能希望最多一次操作1k,但在代码实现里面并没有去限定,而只是在API文档里写了下,这其实是没什么用的。
    同样看到过好多次故障是这原因造成的,所以作为API的编写者,一定要保护好自己,不能因为用的人误用什么就造成严重问题。

  4. 高级的并发中的活锁问题
    并发通常是比较复杂的问题,串行是容易理解的,但一旦并行化,有些时候人很难想清楚,再加上现代的程序通常是多人协作完成的,就更难了。
    并发里面一种超级复杂的是活锁问题,有些忘了具体的case,只记得我们当年在内核层面碰到了一个这样的问题,然后有个妹子竟然自己在脑袋里运行模拟出了这个问题的出现,被一众人惊为天人,反正后来她解释这个问题出现的原因,我听了半天都没听懂...

  5. 系统设计问题
    如果是系统设计问题造成的故障,通常处理起来就会非常麻烦,在我5年前写的《我在系统设计上犯过的14个错》里面有不少case...
    由于大型的系统设计涉及到非常多的集群、子系统、模块,会非常复杂,必须在设计时确保能抓住重心,就像前几天看采访鲁肃的文章里,鲁肃说CTO很大的责任是为CEO扫清障碍和风险,系统设计师很类似,系统设计师的责任是在设计系统时避免系统上线后出现或造成重大风险,并且确保最核心的做系统的目标达成。


印象深刻的历史上的严重Bug


除了这些看过或处理过的外,历史上发生过的严重bug里,我自己印象深刻的始终是1999年火星气候探测者号的故障,摘述下百度百科上关于此次故障原因的描述:

"火星气候探测者号任务失败的主要原因是人为因素,因为火星气候探测者号上的飞行系统软件使用英制单位磅力计算推进器动力,而地面人员输入的方向校正量和推进器参数则使用公制单位牛顿,导致探测器进入大气层的高度有误,最终瓦解碎裂。NASA在此后的所有任务中小心地避免这个因计量单位混淆所造成的错误。”

再摘述下关于这次任务的成本:

“火星气候探测者号总成本是3亿2,760万美元(包含轨道卫星及着陆卫星),花费1亿9,310万美元来研发,花费9170万美元来发射,花费4,280万美元来进行探测任务。”

相当于这个bug造成了这么多钱的损失,如果再加上时间成本那就损失更大了。


之所以对这个故障印象深刻,是因为这个故障其实也是我们在写代码过程中最容易犯的错,就是会默认调用的API是怎么实现的,上面的故障里就是使用API的团队默认参数的单位是公制单位牛顿,但其实API的实现里对这个参数的单位是按照英制单位磅来计算的,这些问题是很难靠什么API文档来避免的,也千万不要靠文档,毕竟执行的时候是只有代码在执行,必须在API上有非常明确的限定和约束(例如在这个故障里的这种是可以要求API上传入单位的),或者就是在代码实现上有明确的约束,高质量的代码之所以难写,很多时候是因为作为API的编写者,需要防范各种误调用造成的超出意期的状况,同时对于要去调用的API最好也能非常明确的知道它的实现逻辑,就像对于运维人员来说,每敲的一行命令,都应该知道按了回车后会发生什么,会造成什么影响。

Talk is cheap, show me the code


最后还是那句话,优秀的工程师,从代码上就是能一眼看出来的,代码的鲁棒性是靠着很多看起来没用的一行一行的代码来做到的。

特别推荐本文作者老毕,19 年获得国家技术发明二等奖、20 年获得国家计算机协会颁发的“ CCF 杰出工程师奖”,沉浮阿里 14 载,江湖人称“毕大师”,这就是前阿里 P10 ——毕玄

他接受了极客时间的采访,做了一个《超级访谈:对话毕玄》的专栏。

这是他第一次以内部视角揭秘阿里的技术演进并且“深度复盘”自己这 20 年来作为架构师、项目负责人的踩坑经验。上线第一时间我就去看了,不由感慨大佬不愧是大佬。

 

这个专栏是以对谈的形式展现,看的时候,仿佛老毕就坐在对面,跟我对话。通过 100 多个问题,他不仅讲了自己从非专业到阿里 P10 的职业成长经历,还提供了不少方法论,比如技术敏感度的培养以及如何做好管理和架构等等。当然,还揭秘了阿里在这 14 年来内部技术演进的一些“不为人知”的故事,比如:为什么 HSF 在淘宝上线第一天就被“回滚”了?跟多隆一起共同参与的“淘宝消防队”到底是做什么的?等等。

相关文章
|
SQL JSON 前端开发
【改BUG】项目遇到的奇葩bug
【改BUG】项目遇到的奇葩bug
|
6月前
|
开发者 C++ UED
你以为的Bug VS 实际的Bug:解密程序开发中的意外之旅
作为开发者,我们在日常开发过程中经常会遇到各种各样的Bug,有些Bug可能很容易发现并解决,但也有一些Bug让人感到困惑摸不到头脑,甚至是无厘头Bug,就像我们以为的Bug与实际的Bug之间的差异一样,让人头大。所以我们在日常开发过程中,一定要细心、细致、细顾,在面对任何Bug的时候都要抱着敬畏的心态去解决,因为我们永远不知道在实际程序开发中的意外是啥,有什么意外在等着我们去发现和解决。那么本文就来讨论分享一下开发者在工作过程中遇到的“你以为的Bug”与“实际的Bug”之间的差异在哪里?,然后通过一个有趣的比喻,我们将深入分析这些不同类型的Bug,还有就是在解决问题时的重要性和挑战。
75 1
你以为的Bug VS 实际的Bug:解密程序开发中的意外之旅
|
6月前
|
UED
面试题7:你写的bug别人都看不懂怎么办?
面试题7:你写的bug别人都看不懂怎么办?
面试题7:你写的bug别人都看不懂怎么办?
|
存储 人工智能
【一】曾经那些错误,你又踩坑了吗?(一)
【一】曾经那些错误,你又踩坑了吗?
66 0
|
存储 编译器 C++
【一】曾经那些错误,你又踩坑了吗?(二)
【一】曾经那些错误,你又踩坑了吗?
83 0
|
Python
遇到bug不要慌,先发个文章看看
遇到bug不要慌,先发个文章看看
128 0
|
Arthas 监控 Java
看了这篇文章,比同事更快找到bug!
你以为程序员只是闷着头疯狂写bug,写好了发布到服务器就完了? 不,你还要修bug!但在那之前,你还要找bug!
213 0
|
存储 算法 Java
10 个让人头疼的 bug
那个谁,今天又写 bug 了,没错,他说的好像就是我。。。。。。 作为 Java 开发,我们在写代码的过程中难免会产生各种奇思妙想的 bug ,有些 bug 就挺让人无奈的,比如说各种空指针异常,在 ArrayList 的迭代中进行删除操作引发异常,数组下标越界异常等。
10 个让人头疼的 bug
写Bug时,需要注意的几点3
写Bug时,需要注意的几点3
126 0
|
算法
写Bug时,需要注意的几点 02
写Bug时,需要注意的几点 02
111 0