2010年12月8日

12項程式設計應該避免的錯誤

一、未善盡責任
基礎知識不足或偷懶,使得程式碼不夠穩固;例如數字計算未事先避免divide-by-zero、將字串寫入資料庫之前沒有檢查最大長度。程式交付到使用者手上,往往都會被以意想不到的方式操作,因此各種潛藏的錯誤都可能發生,甚至造成資訊安全漏洞。
程式語言或開發工具的改善,或許可以幫助我們免於整個系統掛點,例如Java程式的Exception機制,在某個功能拋出Exception時,即使我們沒有加以善後,程式仍然可以繼續執行;但是這些機制並不能真正幫助我們解決問題,因為要解決問題,必須有業務面的考量。舉例來說,執行某功能發生NullPointerException時,如果我們只是catch、顯示error stack訊息之後就置之不理,能夠防止系統crash,對於開發人員也很容易從錯誤訊息得知解決方法;但是對於不了解系統內部設計的end user而言,將很難從中找到修正的做法,例如在執行此功能之前必須先做某項設定之類的操作。

二、過量不必要的細節
假設使用者在網頁填寫一個電子郵件信箱,送到伺服器時必須經過十個function處理,為了徹底防止不正確的資料,每個function都用regular expression檢查信箱格式、並且建立SMTP連線測試是否存在真實的郵件伺服器。這種設計固然做到滴水不漏,但無止盡的過度設計實際上並不可行,因為程式設計必須考量系統資源、網路頻寬、回應時間、開發時程、執行效能等。

三、控制不夠簡化
開發Ruby on Rails應用的程式設計師,會習慣一種「約定取代設定(convention over configuration)」的做法,當程式中建立一個Name類別的model,擁有兩個屬性first及last,那麼就可以預期資料庫中,也會建立命名一致的Name資料表及first、last兩個欄位。程式開發時採用一些約定成俗的慣例,就可以省去很多額外設定的麻煩。

四、對框架過多的託付
框架幫你處理掉很多瑣碎的事情,例如Ruby on Rails將約定的URL格式轉換成controller method呼叫,通常不必知道它怎麼運作。Mike Morton(一位程式設計師)說:「它們(框架)就像用轎子把你抬上九成的山路,但剩下的那一成必須靠你自己攜帶氧氣攀岩才能完成。」

五、太過相信客戶端
我們無法預期網路另一端的使用者怎麼操作系統,就像一個網頁的表單資料,即使我們已經在瀏覽器端用JavaScript做好一些基本的檢查,但送出的資料的過程仍可能遭到惡意竄改,例如使用者用某些瀏覽器外掛,在表單填入原本不允許的資料,或是駭客偽造表單資料進行SQL Injection攻擊。即使是我們自己的程式回傳的資料,只要是來自客戶端,就不該相信它一定照規矩,檢查資料是不是存在威脅很難做得徹底,因此一個好的實踐方式,就是只讓符合條件的資料通過。

六、不夠信任客戶
有時候降低一些對安全的要求,可以讓程式開發比較容易,使用者也比較好操作。例如一個提供八卦閒聊的論壇系統,如果註冊時需要自然人憑證及信用卡驗證,每次登入都需要動態密碼及一連串身分辨識,每一次送出的訊息都經過特殊加密,雖然在資安方面可能有極高的成效,但肯定不會是個好的系統。

七、重度依賴神奇魔術盒
當你買了一個神奇的資料庫備份軟體,你不必管它怎麼運作,因為銷售員告訴你「It just works.」是否就此高枕無憂,再也不必擔心資料庫發生問題?許多買來的函式庫、開發工具很好用,我們只需要知道怎麼用,而且大部分的時候它都很順利,但是有一天它鬧個彆扭,災難就此發生。

八、重新發明輪子
如果你需要一個加密的演算法,應該要找一個好的演算法實作,如果覺得它不夠好,那麼就動手去改善它(如果是自由軟體那麼更需要這樣做);反之,如果你丟棄別人已經辛苦幾年做出的成果,想要重新打造一個自己專屬的演算法,那不僅是浪費時間,也等於是向駭客敞開大門。

九、過多的功能讓使用者困擾
智慧型手機的兩大主流平台,iPhone及Android各自有其愛好者,Android在安裝新軟體時,很詳細地將新軟體有哪些存取權限告訴使用者,讓使用者自己判斷新軟體潛在的安全問題,例如一個可以存取SIM卡資料的軟體,就有可能透過網路把你的個人隱私洩漏出去。但是對於end user而言,根本看不懂這些涉及技術面的問答題,他們最後還是會在不懂有哪些潛在危害的情況下確認安裝。iPhone贏在操作起來"通常"比較簡單,讓完全不懂科技產品的消費者,也能很快就愛上這款新奇的科技產品。試想在登入一個網頁時,你還要選擇是否啟用SSL、GZIP網頁壓縮,要發表一篇文章時,還要設定使用哪一種所視即所得編輯器,使用者哪管這些?大多數人喜歡的系統就是,方便、不必太多思考(參考 Don't make me think)。

十、使用者想的和你不一樣
有些Web郵件系統沒有「新增子資料夾」的設計,但可以用標籤來達到同樣的功能,標籤比子資料夾好用,因為一封郵件設定了多個標籤,就有同時存放於多個資料夾的效果。但並非每一位使用者都願意接受這種操作模式,他們就是喜歡先建好一堆樹狀的資料夾結構,等真的收到郵件的時候,再決定分類到哪個資料夾。

十一、封閉程式碼
許多發展商業軟體的公司,總喜歡用盡各種手段保護程式碼不會洩漏,不但要編碼加密,還要加入防止逆向工程的設計。對軟體公司而言,程式碼是一項資產,要把它分享出去,是件有挑戰的事。並不是每一種程式碼都是需要保護,有些程式碼可以公開,可以藉由分享變得更好;例如在一個專案中,實作了一組方便的郵件發送函式庫,把它公開分享,並不會影響專案的收益,卻能得到知名度的提升及使用者意見回饋的好處。

十二、開放不是萬靈丹
有大量的開放源碼專案在SourceForge、GitHub、Google Project Hosting等網站上線,但僅有少數能夠獲得人們參與維護、修正及擴充代碼。如果軟體專案缺的是人力,即使把它變成開放源碼的方式分享出去,也不見得就能獲得問題的解決,因為很容易找到其他相似的替代品,即使現在沒有,也會在未來出現。而且將產品開放,可能也意謂著將失去財務上的支持,更可能被拿去做違反自由軟體精神的應用,例如某些程式碼被拿去開發成商業產品的一部分,並且衍伸的程式碼並沒有同樣分享出來或回饋給創始者。

參考資料

2 則留言:

  1. 哈…說得好,但要做得好恐怕有點難吧!
    因為這12點裡,講的都是取和捨之間的拿捏,多一分不該、少一分不夠…這…嗯…要靠練習累積經驗,才能做得恰到好處吧!

    回覆刪除
  2. Rule 1. There are no rules.

    Rule 2. Follow the rule 1.

    回覆刪除

lyhcode by lyhcode
歡迎轉載,請務必註明出處!