0 error 0 warning 那是小意思。知乎程序员大概人均都能做到。

至于 0 bug 嘛。。。我跟你说个事儿:图灵奖得主高德纳为自己号称没有bug的TeX软体开出了悬赏,每找到一个悬赏加倍,迄今为止,他的支票已经达到了20.48面额,这意味著他至少已经开出去了十一张支票。(实际上更多,不过中间有一次他作废了几张支票,然后又从2.56开始,所以就算11张吧)

这个软体本身只是一个核心,而且功能很多年都没有改变,尚且没法做到 0 bug。可想而知零bug有多难。

连大神都做不到的事,咱们还是别搞不切实际的幻想。

--

什么你说是2000行?2000行那不叫一个程序,那叫一个模块,或者,一个单元。2000行的程序没必要纠结这些问题。


以前高中时候天天写代码的时候有可能一遍过testcase,不过当时warning基本上不管的,也很少有2000行这么多。现在基本上写2000行肯定会因为注意力分散写出几个错误的。

比起一遍写对来说,介面一遍设计对、有足够多调试日志可能更重要一些,如果能做到只有笔误级别的错误的话,一般有编码的1/10不到的时间就可以调对了。更长一些的代码应该从一开始就规划好分模块调通的步骤。如果是计划长期维护的代码,那一开始就应该把单元测试也写好,这样调试的时间就更可控了。


不知道,简单点的代码在脑子非常清醒的过程下可能可以吧。现在上了年纪了,就不太行了。

如果算上代码生成器生成后的代码的话,那应该很容易了,比如flex和bison生成出来的代码。

纯手撸,个人最高纪录是1000左右行的C内核模块,3天左右写完,1个编译错误,QA测出来了5个bug。

另外,还写过1000-2000行左右的的O1的slab memory和hash table,编译错误多少不记得了,但是至今0bug,到现在还作为产品的基础模块运行著。


好多人没概念,但2000行其实已经算很长的代码了。大部分系统软体早期的核心代码也就在1-2万行:

  • linux最早那个版本只有「10,243 lines of C and 386 assembly」
  • Hadoop最早的版本中,HDFS大约5000行,MapReduce大概6000行
  • Spark论文里面说了他们写了大概1.4万行代码

写2000行0 error 0 warn还是可能的。但0 bug?那是因为你还没发现。。。


这有什么难的,各种代码生成器随便就能生成几万行代码 0 error、0 warning还有0 bug……


当你调试完,通过所有测试,达到了0error0warn0bug的时候,等到上线后,你永远不知道哪天会不会有一名顾客点了一份炒饭把酒吧炸了。

一个测试工程师走进一家酒吧,要了一杯啤酒;

一个测试工程师走进一家酒吧,要了一杯咖啡;一个测试工程师走进一家酒吧,要了0.7杯啤酒;一个测试工程师走进一家酒吧,要了-1杯啤酒;一个测试工程师走进一家酒吧,要了2^32杯啤酒;一个测试工程师走进一家酒吧,要了一杯洗脚水;一个测试工程师走进一家酒吧,要了一杯蜥蜴;一个测试工程师走进一家酒吧,要了一份asdfQwer@24dg!*(@;

一个测试工程师走进一家酒吧,什么也没要;

一个测试工程师走进一家酒吧,又走出去又从窗户进来又从后门出去从下水道钻进来;一个测试工程师走进一家酒吧,又走出去又进来又出去又进来又出去,最后在外面把老板打了一顿;一个测试工程师走进一家酒吧,要了一杯烫烫烫的锟斤拷;一个测试工程师走进一家酒吧,要了NaN杯Null;一个测试工程师冲进一家酒吧,要了500T啤酒咖啡洗脚水野猫狼牙棒奶茶;一个测试工程师把酒吧拆了;一个测试工程师化装成老板走进一家酒吧,要了500杯啤酒并且不付钱;一万个测试工程师在酒吧门外呼啸而过;一个测试工程师走进一家酒吧,要了一杯啤酒;DROP TABLE 酒吧;

测试工程师们满意地离开了酒吧。

然后一名顾客点了一份炒饭,酒吧炸了。


如果是自己重头写的2000行左右的小工具(不涉及外部系统,或者对所涉及的外部系统了解非常深刻,完全掌握什么样的输入会有什么样的返回,也就是说外部系统没有副作用),完全可以呀。

我是说,如果你用枪指著我的头,只要我的这个小工具第一次运行有bug就一枪爆头,但又不限时间不限精力(期间可以吃饭睡觉),我大概率能活下来。

理论上,我只需要能不计成本保证二十行的代码首次运行无bug。然后我只要自我限制每个函数不超过二十行,别说2000行,4000行都可以保证无bug。虽然我不知道如果不是被人用枪指著头的话为啥要这样搞。


普通人不大可能,大神不知道。

让我写个2000行代码,出个十几个错在所难免,甚至有时候还会漏打分号。

但是我还算是不可替换的业务骨干。因为对业务有透彻的理解,写出来的逻辑正确,框架清晰,大方向把握比较准,演算法方面也不会掉链子。语法上不确定可以上网查,所以你让我换一个语言,上手的速度也非常快。

别听一些培训机构或者老师忽悠你,编程序不要有语法错,没有语法错,就是大师就是高手。

错。

现在越来越智能化的集成环境,智能补全的功能已经登峰造极,检查越来越严格的编译软体,都能帮你把简单的基本错误全部揪出来,指出位置和错误名称,你照著改就行了。

作为高级程序员的价值,在于透彻的理解并且实现业务逻辑,在于利用物理和数学方法建模型并精准的解决问题,关于写出合适的演算法解决合适的问题。

还有,其实编译器查不出来的bug才是真正可怕的,不是吗?


首先,我曾经写过4K行代码(就是闲,自己闲的蛋疼跟同事比,QT + VS2015 + C++ + CAMKE + MSVC),编译没有问题,没有任何警告,也"自测"过了

**程序员自测** 你懂得

然后我看著我的代码慌了1天.....真正意义上的一天.

结果?天道好轮回,天崩地裂(CPP应用)..


我前年倒是真有过1500行代码0 bug的经历,至于有没有error和warn倒是记不清了,姑且假设没有吧。

这个0 bug呢,说出来大家当然不信,其实我自己也不信,但是场面上呢,它的确是0 bug。

前年跳槽到了新公司,加入一个刚成立不久的新团队,原来团队里面的技术骨干呢,对我这个空降的技术领导自然是不见得满意的。

先划著水摸了两个月的鱼,算是大概摸清了情况,来了个紧急任务,经理大概也是想要考验我一下吧,让我想办法搞定,从想方案从到设计到编码到上线总共两周时间。

是的,这个任务甚至连个方案都还没有,我们唯一知道的是我们可能需要写一个通用library,然后在业务系统里面再调用。业务上要做的事情很简单,它之所以变成一个正式的任务,就是因为上头的大佬不能容忍我们在业务系统直接打个补丁了事,要求必须出一个通用方案可以共享到别的系统中去。

我花了三天时间,烧了不少脑细胞,想出来一个不错的点子,跟几个相关的团队开会确认了可行性,写了个简略的设计文档再评审通过,嗯,已经过去4天了,还剩下6天。

开始写代码吧,花了两天时间,堆出了1000多行代码,早会跟大家商量了一下,为了节约时间,虽然代码还有点脏,还是先把PR发出去给大家review,看看有没有结构上的问题或者明显的疏漏,我再平行的整理代码补充单元测试什么的。

记住,这时候还有4天时间了。我把PR发出去,特意说了,代码还有点脏,请主要关注结构问题以及有没有重大疏漏的bug,单体的edge case我还在补。

发出PR后,我埋著脑袋又工作了一上午,感觉也整理得差不多了,打开邮箱一看,妈呀,60多个comment,仔细一看,全是一个哥们儿写的,主要内容是什么呢?

  • 这里缺javadoc,那里缺javadoc,写了十几个之后,总结一个,整体上,没有javadoc,这个PR太糟糕了,再附上一个javadoc的官方链接(这里应该手动doge)
  • 考虑到这个library的想定用途是非常靠近底层的通用功能,处于性能考虑,整体上我的代码是非functional风格的(这个决定倒是的确值得商榷),于是,在所有他认为应该functional的地方都会留下评论,嗯,再加上java 8 stream api的blog链接(5年scala程序员一脸懵逼)
  • 各种变数命名不合他的心意
  • 各种缺乏单元测试(啊,大哥,我知道啊,大家都知道啊)
  • 有个地方的逻辑需要做字元串匹配,完整严谨的逻辑需要一个上下文无关的parser,我显然没有足够的时间来做这个事情,于是就写了两个正则表达式来匹配,然后注释说,这次上线我们只需要验证这两种情况,等上线后这里会重写一个上下文无关的parser。既然我只有两个case,当然是简单的ifelse判断一下就好了,他的评论说,要是这里有100种case你这个ifelse会变得非常丑陋。。。(嗯,所以大哥你是眼瞎吗?)
  • 一个方法遍历一个List&做点事情,传入参数的名字是values,循环变数我写的v,注意,这个方法总共就三行代码,他评论说,变数名不能这么简略,经理偶然看到了这个,问他为啥不能这么用,他说,将来这个method会变得非常大,就没人知道这个v是什么意思了。。。经理作为前程序员,当时也石化了。。。

(别急,0 bug的事儿在最后)

我看他这评论的架势来者不善啊,(省略各种撕逼)找到经理了:

  • 这哥们儿写这么多是恶意还是善意?
  • 听说我来之前咱们team没有代码规范文档是吧?我作为技术领导进来,这事儿好像是我的业务是吧?这哥们儿的意思是我们这team的规范他说了算?还是我说了算?
  • 还剩3天了,你这意思是上线还是不上线?

经理回头强按著他approve了代码,上线发布了。我就等著,等到灰度结束,全体上线第二天,找到经理了:

哎,问你个事儿,你觉得我的代码质量怎么样?1500行代码,0 bug,还算可以吧?对得起公司给我定的级哈?

经理一脸懵逼,大哥,啥意思?

嘿,也没啥意思,我那个PR,1500行代码,收了60多个comment,没有一个跟bug有关,这不,都上线了,你信不信我1500行代码没bug?你别说,我自个儿都不信我这么牛逼。

经理崩溃了。。。

我0 bug成就达成。。。


之前手撸过AVL树。

用Python来的,运气很好,0EWB。

然鹅第一次运行的时候有逻辑错误。。。不过这个玩意,其实也算Bug。

说了这么多,就是想说一句,代码量和代码是不是能被编译运营都是次要的,更重要的是逻辑。能不能解决这个问题,在有了思路的基础上,必要的轮子能不能造?调包你会不会调?我觉得这才是更重要的。


你的这个问题就像是在问一个篮球运动员,能不能把球顶在手指头上旋转1个小时。

可能有的运动员确实能做到,但能是能,这样做又有什么用呢?抛弃别的训练天天去练转球?

这个问题对程序员也是一样,如果我把一行代码复制一千遍,是不是也是一千行无bug呢?

你可能说我这是在作弊,那我就全神贯注一天,每写完一行都完整的检查一遍,最终做到了0bug。

但我为什么不花一个小时写完代码,另一个小时改bug呢?

所以说题主这个问题完全没有意义,他根本就是一个外行,听了几个关于程序员写bug的段子就以为判断一个程序员水平高低的方法就是看他写不写bug。

或者是题主才学了个c语言,对这方面只是仅仅入了个门。这时候写的c语言练习题也就几十行最多一百多行的水平,肯定很羡慕一些所谓的「大项目」,也很好奇是不是大佬完全不写bug。

这只能说明题主对这方面了解到还是太少了而已,就像你不能用点钱的快慢来判断一个会计是否优秀一样。同样,计算机这边知识也是无边无尽的,代码打的快的不一定厉害,不出错的也不一定就是大佬。


要做(在某种意义上)也能做到,但是纯粹是为了做而做。比如写2000行肯定safe但是没有任何有用功能的代码。

现实工程当中,基本不太可能。

(以C++开发为例)

因为:

  1. 既然是大佬亲子操刀,肯定不是在完全重复已经做过的东西,那么总有不太清楚的地方
  2. 肯定要用到平台提供的代码。这些代码本身就不是0 warning 0 bug的。比如,你开msvc -Wall的话,就会发现系统头文件一堆warning
  3. 有些warning并不是问题,有些甚至只是提醒。比如某个API快要过期了,比如最新的C++标准这里有些变化,等等
  4. 不同的编译器之间就有差别,有些还是矛盾的,特别是在C++新标准方面。这边不报了那边报,这是没办法的事情。
  5. 0 bug这件事情虽然不是完全无法证明但是基本上是无法证明的


如果找一个状态好的时间全神贯注,可以做到。但是这样做毫无意义。如果是一边听音乐一边刷知乎,肯定就做不到了。

但是,为什么要一遍通过呢?意义何在呢?

编程的技能本来就包括编码、调试、测试,三种技能都很重要啊。三管齐下,将程序「写」正确即可。

忽略另外两种,单纯追求一种成为高手,路子本来就偏了。


可以一次过的。

但是你要注意,在他动手写代码之前,所有的逻辑,代码的结构,都已经在脑子中想的明明白白,清清楚楚了。

打个比方,

可能思考:5天;

然后编码:1天;

测试:0bug。

大部分人是,

直接上手编码:1天。

测试迭代:无数次;

修改:无数次。

测试人员时间:5天。

自己修改时间:7天。

最终成果:潜在若干bug的缝缝补补新代码一份。

这也是高手与低手很重要的区别之一。。。。。。


一遍过倒是经常的事,尤其是在有 IDE 帮助的情况下,有建议、有警示,很少在编译时出现 error 和 warn。

不过,0 Bug,这个就难说了。当下测试看起来没 Bug 的,或者 Unit test 覆盖率 100% 的,也有可能在日后某个特殊情况下,或被其他人调用时出现 Bug,或不够完善的情况。

另外,个人来说,一次性写上千行代码然后一次性集中编译,别人有没有这么干不知道,我应该没有这样的经历,最多也就敲上几十上百行,就得构建一次试试。

综合来说,0 error 0 warn,及格水平。0 bug,这不好说,反正我的代码是经常改的,可能当时没问题但日后看写得不太好,逻辑太混乱、冗长,然后改了改,结果改出 bug 来了。


软体工程,形式化验证,了解一下


我写过不计其数的bug

也修复过不计其数的bug

#################################

当第一眼看到这个问题,我想起的我的小外甥。有一天他兴高采烈的玩耍,然后不小心被小刀割破了手指。他呆呆的坐在沙发上,看著缠著创口贴的手指,眼神中充满了哀怨,仿佛在说:「怎么办,我的人生不完整了」

2000行0 error 0 warn 0 bug。就好比我的小外甥在兴高采烈的玩耍。

但那一个命中注定的error会到来的,你的人生终究会遇到「不完整」的那一刻。

然后上了年纪后,你会身经百战,bug等身,浑身遍布刀创斧凿的痕迹。那会儿回头看看,这两千行算不了什么,两千万行两万个BUG,这才是正常水平。水平高的少一点,水平差的多一点罢了。


最多也就是码农民工的水平,因为你一定是在写2000行幼儿园级别的1+1=2,否则不可能一遍过,也许有人讲一大堆理由告诉你代码就应该一次写对,当然这只是胡吹瞎扯。好代码不应该是调出来的,但也是不断修改推翻再修改重构出来的。error warn 和 bug就是这个周期的体现。代码体现的是思想,思想就是探索和试错。


一个测试工程师走进一家酒吧,要了一杯啤酒;

一个测试工程师走进一家酒吧,要了一杯咖啡;

一个测试工程师走进一家酒吧,要了0.7杯啤酒;

一个测试工程师走进一家酒吧,要了-1杯啤酒;

一个测试工程师走进一家酒吧,要了232杯啤酒;

一个测试工程师走进一家酒吧,要了一杯洗脚水;

一个测试工程师走进一家酒吧,要了一杯蜥蜴;

一个测试工程师走进一家酒吧,要了一份asdfQwer@24dg!*(@;

一个测试工程师走进一家酒吧,什么也没要;

一个测试工程师走进一家酒吧,又走出去又从窗户进来又从后门出去从下水道钻进来;

一个测试工程师走进一家酒吧,又走出去又进来又出去又进来又出去,最后在外面把老板打了一顿;

一个测试工程师走进一家酒吧,要了一杯烫烫烫的锟斤拷;

一个测试工程师走进一家酒吧,要了NaN杯Null;

一个测试工程师冲进一家酒吧,要了500T啤酒咖啡洗脚水野猫狼牙棒奶茶;

一个测试工程师把酒吧拆了;

一个测试工程师化装成老板走进一家酒吧,要了500杯啤酒并且不付钱;

一万个测试工程师在酒吧门外呼啸而过;

一个测试工程师走进一家酒吧,要了一杯啤酒;DROP TABLE 酒吧;

测试工程师们满意地离开了酒吧。

然后一名顾客点了一份炒饭,酒吧炸了。

***

侵删


推荐阅读:
相关文章