1947年9月9日,美國海軍准將 Grace Hopper 在哈佛學院計算機實驗室裏使用 Mark II 和 Mark III 計算機進行研究工做。她的團隊跟蹤到 Mark II 上的一個錯誤,操做人員發現是因爲一隻飛蛾鑽到了 Mark II 的繼電器裏致使的。團隊清除了這隻飛蛾,一切恢復正常。當時的工做人員記錄了這樣一句日誌:" First actual case of bug being found. " 此次著名的事件,猶如潘多拉打開了魔盒,今後,程序員的世界裏,bug 滿天飛。前端
世界上第一個 bug程序員
在我所擔任過的角色中,有一個崗位叫作 Development Manager,一般簡稱 DM. 記得在一次基於一款平臺的二次開發項目中,由於 bug 實在太多,咱們幾乎拿出了一整個里程碑的週期來 debug,因而我這個DM有了新的解釋:Debug Man.npm
沒有人喜歡 bug,bug 意味着錯誤、不肯定性、加班、交付風險,等等…… 負面的詞語怎麼堆砌都不冗餘。隨便找個有過1、兩個項目經驗的開發者,問問他 debug 的回憶,那氣氛就跟上墳同樣。編程
對於 bug,開發者的神經每每也很敏感。有個段子頗有趣 —— 說的是「應該如何向程序員反饋一個 bug 」 ——app
你不能直接跟他說:「這裏不對啊,是否是你程序有 bug 啊?」,要這麼說的話,會直接被懟回來:「你丫的本身不會用吧!」。框架
你能夠換個說法:「咦,這裏好像不對,是我操做錯了嗎?」,這時程序員內心就一咯噔:「Shit.. 不會是我代碼有 bug 吧?」編程語言
從業多年,發現有個現象還蠻有趣的:有時候,當某個 bug 被發現時,犯下這個錯誤的始做俑者會開玩笑地爲本身解脫:「誰沒寫過 bug 啊,Windows 還有 bug 呢。」 這句託詞我也用過,感受挺好用的,就比如:梅西都能罰丟點球,我空門沒進,也是能夠理解的嘛。函數
但其實吧…… 這邏輯經不起推敲的。工具
Windows 操做系統,一款長達30多年,裝機量估計都超過了地球人口數量的巨型工程,複雜度基本只能靠猜。以微軟公佈的資料來看:單元測試
Windows 95 代碼量約 1500 萬行
Windows XP 代碼量約 4500 萬行
Windows Vista 代碼量約 5000 萬行
Windows 7 代碼量 5000+ 萬行
以 Windows 7 爲例,超5000萬的代碼量,23個小組,共1000多人的開發團隊。如此規模下產生的bug,和一個在辦公室裏上了1天班,寫了200行代碼,就鬧出一堆bug,搞得項目亂七八糟的,能同日而語嗎?最後再輕描淡寫地來句 「微軟也有 bug 」,不害臊?
因此我後來不用這句了,如此開脫,水平太low。其替代方案容我稍後再講。
爲了對抗 bug,人們發明了各類各樣的工具和手段,上至方法論,下至生產工具。愈來愈先進的 IDE, 複雜的代碼審查制度,從單元測試到集成聯調,再配上 beta 版,試用,公測,等等。凡此種種,其目標無一不是消滅 bug 。可這些琳琅滿目的解決方案的存在,反倒證實了一個悲劇:人類,實在是太容易犯錯了。
若是說凡事都有正反兩面的意義,那麼 bug 的正能量就是硬生生造就了大量就業機會,進而維護了社會穩定。
那麼,爲何咱們老是沒法避免 bug 的產生?咱們能不能杜絕 bug ?
答案固然是不可能了。由於那樣一來,程序員的日子豈不是太舒服了?不符合苦逼的定位。並且,咱們所處的這個世界,但凡越是高呼要消滅的東西,越是會廣泛地存在。就像蒼蠅、蚊蟲、污染、犯罪、戰爭,不一而足。
按照常識,經驗越豐富的老手寫出來的代碼,一次經過的概率更高,好比他們思考得會更周全,對異常的判斷和處理更老練,邊界條件把握得更精確,等等。因此咱們可能會幻想:是否是隻要咱們足夠仔細,並努力磨練技藝,經過讓一部分碼農先老練起來,而後實現共同老練,最終就能夠達到全世界開發者聯合起來消滅bug的大解放了?
很遺憾,這只是一個治標不治本的思路,由於bug是有階級的。老手們的bug相對少,只是低級錯誤少,他們也會遇到bug,而他們的bug,每每都是一眼蒙逼的難度係數N.x的難題,不發生在代碼層面,大多在業務層面,甚至需求設計層面,或者直接是一些不可抗拒因素(作過政府項目嗎?)。總之,萌新有萌新們的秀逗,大叔有大叔們的短路,老杆也會有本身的滑鐵盧。
bug 這個概念的起源,就預示着它的不可避免性。世界上第一個 bug 是一隻飛蛾,這劇本,誰能料到?某種意義上說,bug 就是不可預見的錯誤,能被預估而且提早作好準備的,那叫 exception, try catch 是他們的朋友。
對於爲何會產生 bug 的緣由,著名的荷蘭計算機科學家 Edsger W. Dijkstra 有過一句經典名言:
If debugging is the process of removing software bugs,
then programming must be the process of putting them in.
這就是上文提到的那句託詞 「 Windows 也有 bug. 」 的替代方案。:)
設想一下,當你從無到有的寫下一句句代碼時,中間的任意一個時刻,你的程序都是運行不起來的,至少也是達不到目標效果的。從效用上徹底等效於充滿 bug 的一堆代碼。你可能會辯解,程序還沒寫完呢,只是功能還沒實現,並無 bug 。事實上,換位思考一下,缺失某個功能和包含一個有故障的功能,對於用戶而言,都是無用的。一個處於開發階段尚沒寫完的代碼和開發結束但寫得有缺陷的代碼,是一回事。
由此能夠引伸出了一個著名的命題:
That's not a bug, it's a feature request.
有時候,咱們很難分清楚一個問題到底屬於 bug 仍是 feature request . 文中做者拋出了一個案例:用 Visual Studio 構建一個 Windows GUI 程序時沒有采用系統默認字體。這個算不算一個 bug 呢?
很差說。畢竟,隨着軟件應用愈來愈普及、愈來愈追求所謂人性化的趨勢,傳統意義上的只要程序能運行就不算 bug 的觀點,也在慢慢發生改變。對於一個強迫癌用戶來講,UI 上有缺陷,那基本上整個軟件就不能用了。事實上,在當今各種 app 競爭白熱化、同質化的時代,用戶體驗上的問題,每每是致命的。之前你們沒得選,因此沒那麼挑剔,只要程序能幹活就好了。現在的計算機用戶已經被寵壞了,在這樣的時代下,bug 早已悄悄地泛化了。
因此,到底如何才能寫出沒有 bug 的代碼呢?
答案: 不寫代碼。
一個悲觀又絕望卻正確的惟一解。
試着在這絕望裏挖掘一點但願吧。這個答案隱含了一個方法論: 儘量少寫代碼。由於 Dijkstra 大師已經說得很清楚了,編程就是製造 bug 的過程。那麼,代碼寫的越少,犯錯的概率就越小,這個道理顯而易見。維護一段300行的代碼,咱們很容易有信心;接手一段3000行的代碼,什麼反應就看各人素質了。
現代的開發方式也都包含有這個思路,從 IDE 的智能提示,代碼補全功能,到每門語言都會有的各類「21天從入門到精通」的開發框架,以及不少實戰層面的約定俗成,都是在幫助開發者減小沒必要要的編碼。框架化、規範化思惟能下降出錯的可能性。
事實上,就連編程語言自己的歷史發展都是按照這個思路在進行。從底層的彙編語言,到C/C++,再到Java/C#/Python……等各類高級語言,語言演化的目的之一就是爲了把程序員從髒活、累活的工做中解放出來。
「不要重複造輪子」的精神,一方面是在指導咱們提升效率,不要重複勞動成本,另外一方面也是減小重複犯錯的概率。
當代 Web 開發中的各類包管理概念正深入地踐行着這條精神,以致於在2016年3月爆發了著名的 NPM & left-pad 事件: 一段區區11行的字符串填充函數模塊,被全世界依賴,結果做者 Azer 下架模塊包的那一天,全球前端大崩潰。受波及的產品和團隊中,甚至包含著名的 React !
這個事件讓人們開始反思:咱們是否是忘了該如何編程了? 一個功能簡單到人人都會寫的函數,卻都不約而同地選擇引入,而不是本身實現。最終,過猶不及。
寫代碼,真的很難。
NO BUG , NO CODE .
但是,若是真的只能不寫代碼了,那麼自己就已經沒有女友的程序員們,如今連代碼也沒有了,這還讓不讓人活了?
不能這樣把程序員們給逼死了,要講人權。
有時候,當答案實在不可接受的時候,咱們就該思考是否是問題問錯了。
因此,換個角度,爲何要追求無 bug 呢?也許咱們根本就不必懼怕 bug.
有 bug 的地方就有麻煩,有麻煩就有解決麻煩的須要,客戶就是給那些能解決麻煩事的人支付報酬的。只處理簡單的問題,是沒有價值的,市場只承認那些面對困難能提供解決方案的人。簡單來說,想賺錢,就別怕麻煩。
對於客戶來講,無論是 bug 或是 feature request,都是一個須要解決的問題。一個優秀的PM,能夠把客戶反饋的 bug,包裝成 feature request,返回一套解決方案。而後,優秀的商務表明出馬,簽定補充協議。恭喜,大家的項目經費增長了一點點。
英格蘭有句諺語:
Where there's muck, there's brass.
如此看來,「 如何寫出沒有BUG的代碼?」 這問題,恐怕確實問錯了。
本文已獨家受權給腳本之家(ID:jb51net)公衆號發佈