第42章 修複b

  晚上。


  已經和王曉雪收拾好了明天需要帶回家的東西之後,葉新晨就打開了曹慶陽發給他的東西。


  趁著現在時間還足,所以葉新晨也是準備直接花費一點時間幫曹慶陽給搞定。


  打開文件,葉新晨看著這個代碼,陷入了沉思,他陷入沉思的原因不是因為這個修複漏洞很難,相反,很簡單,葉新晨半個多小時就給他修複好了。


  他感覺到的隻是修改BUG和找BUG那真的是兩個情況。


  不過有些人也肯定很疑惑,程出現BUG是必然出現的情況還是程序員水平有限導致的?


  這個嘛……仁者見仁,智者見智。


  就比如這個——


  print(“hello,world.“)

  你看,這個“程序”就是沒有BUG漏洞的……


  實際上但凡有過一點正式開發經驗的程序員,寫個簡單的helloworld都能寫出BUG的恐怕不多見吧。


  別說helloworld了,一個簡單的、不涉及“隱秘”機製的百行小程序,絕大多數資深程序員也可以直接寫成0bug。


  因為這些實際上是對計算機的原理深度決定的,比如你對計算原理或者語言機製理解越深,對你來說“隱秘”的東西就越少,寫出高質量代碼的機率就越高。


  而且,就像黑土平台裏麵的交流板塊哪怕隻是在上敲一篇一千個字的灌水文,有幾個可以保證無語法錯誤、無錯別字且標點符號使用正確呢?

  尤其這還是在機器替你寫字,使得“提筆忘字”“書寫錯誤”之類錯誤無法存在的前提下:這樣你都不能保證全對……


  那麽不僅大小寫敏感、而且邏輯更為曲折複雜、容不得半點含糊的計算機程序呢?

  因此,有BUG漏洞那真的是無可避免。


  當然還有一種情況,你的程序本身是無bug的;但支持環境比較坑……


  這種正常來說不算程序bug,當然實踐中,你可能沒辦法坐等OS或者瀏覽器等廠商修改——所以結果就是你隻好積極行動起來,在自己的程序裏為別人的錯誤擦屁股……


  這在業界被稱為workaround:Workaround-Wikipedia。


  正常來說,workaround是臨時的,並且,如果不是諸如0day之類特別關鍵、刻不容緩的問題,搞workaround往往是出力不討好的——因為它包含了醜陋,易錯,含糊,難以理解;而且等OS或者瀏覽器等的原始廠商修了它自己的bug,你原本好好運行的workaround往往反而會引起問題。


  尤其是,有時候OS或者瀏覽器廠商修複速度比較慢、致使某種workaround反倒成為“主流技術”;那麽當“正統”修複方案和workaround衝突時,OS或者瀏覽器廠商往往不得不將錯就錯,以免搗毀那些用了workaround的實現……


  這類複雜情況暫不討論,提它主要是為了說明,搞清楚bug的真正發生點是極為重要的。


  修不到bug的根源、濫用workaround,度過的是眼前的難關,犧牲的卻是整個項目的穩固性。


  類似的,盡量把程序寫的“大眾化”一點,沒有必要不碰新特性,也可以在很大程度上避免“遭遇官方bug”問題——如果你自己理解上再有點偏差,用新特性就和作死無異了。


  不過……


  有的人敲字灌水都錯字連篇,但是有人手寫幾十上百萬字的小說,隨便截一段都差不多能進語文課本……


  所以,人與人還是有極大差別的。


  不能因為“Linus也寫bug”甚至“Linus也寫過低級bug”,就認為“我寫個一百個整數裏找最大值的簡單程序出三十個bug也是正常的”——初學者搞出這事,正常。


  至於專業人員嘛……出一個都不正常。


  不僅如此。


  既然“寫長篇出bug正常,發條短信就那麽十幾個字,錯一個都不應該”;那麽我們把長篇拆開成若幹章,一章隻寫三千字呢?再把一章拆開成若幹段,一段隻寫數百個字呢?

  這就是為何寫程序要先做模塊設計、然後再把模塊按職責拆分成類、類按功能拆分成函數、最後還要求一個函數不要超過一屏(大約80行)的原因了。


  經過拆分之後,一個一個函數填寫實現、然後再一個一個函數做單元測試,測完再組合起來搞功能測試、集成測試……


  這樣寫程序,當然還是無法杜絕bug出現;但出bug的機率就微乎其微了。


  而且程序和長篇小說不同。


  小說裏的角色,尤其是主角和主要配角往往是貫穿始終的,這就使得小說章與章之間存在很多內部聯係;稍微搞不好就會導致前後失去呼應,比如主角一會兒傷在左手一會兒傷在右臂、或者前麵挖個坑然後設個伏筆後麵卻忘了用,等等。


  但是在程序裏麵,不同模塊甚至不同函數之間,應該是毫無瓜葛的,每一個都可以摘出來獨立成庫——有瓜葛就說明用了全局變量或者靜態對象,或者通過參數或者約定等傳遞了過多的東西——這就叫“低耦合”。


  做到了“低耦合”,你就可以把一個複雜的大程序當一組簡單的短文甚至短信寫。


  這樣自然就很難出錯了。


  當然了,有些情況下,程序邏輯非常複雜且無法拆分,也就是所謂“無法約分的複雜性”,這種代碼就必須端起十二分小心來,當然即便如此,bug出現率仍然要遠高於其他代碼。


  一般來說,要把程序拆成“不可約分”的一組最小單元來寫。


  這個“不可約分”就是術語說的“高內聚”:這段程序隻做一件事,這件事已經沒法拆的更簡單了,隻能把它們放在同一段代碼裏一舉解決掉。


  因此,寫程序時,事先的“謀劃”非常重要。


  一個有經驗的資深工程師,可以在動手前就把一個複雜的大項目拆成一堆幾乎互不關聯的小程序,然後逐一實現它們、實現完再把它們組合起來就行了。


  顯然,“謀劃”好了,一個程序的難度降低若幹個數量級都是可能的。


  說實話,在絕大部分能見到的軟件中,都是或多或少的有bug的……


  隻不過,第一開發可能沒想到,第二測試沒測到,第三用戶沒碰到,第四客服的反饋沒收到,那麽——這就是一個“成熟穩健”的產品。


  PS:留個言,你們是不是不喜歡看代碼相關的或者看不懂這些……說出來我以後少寫點,畢竟前期還是需要程序員的技術去賺錢的。當然你們的意見我也考慮一下。

上一章目录+书签下一章