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 酒吧;

測試工程師們滿意地離開了酒吧。

然後一名顧客點了一份炒飯,酒吧炸了。

***

侵刪


推薦閱讀:
相關文章