這種文章大家看了很爽,但好像沒什麼建設性?
小年夜那天筆者是最後離開公司的 RD,那天花了一整天想找出系統崩潰的原因...
最後關上電腦離開大門時,覺得有些事情不該這樣,覺得有些開發經驗、在不涉及公司機密的情形下分享出來,是不是可以造福大家、避免重蹈覆轍?
本文盡量不談一些容易引起爭議的地方,尤其是容易參入人為因素的部份,如軟體架構、Code Review....尤其後者有時快變成整肅異己的工具了...:(
也歡迎各位發表意見,讓我們一起提昇台灣軟體設計的品質
(因為這幾年都在搞 Embedded Linux + C/C++,所以整體偏向 Linux 為主)
未慮對,先慮錯
我司曾經發起「軟體品質改善計畫」,不過後來就跟太監一樣下面沒有了
話說回來,確保基本的軟體品質真有那麼難嗎?
以筆者的經驗來看,至少可以從幾點入手(也歡迎大家發表高見)
事先預防
- 運用 compiler 分析程式,例如 gcc -Wall。
- 使用靜態分析軟體,如 cppcheck,如果願意投資 pc-lint 更好。
- 使用 assert 查核參數,與確保迴圈不變式(Loop invariant)成立。
- 結合 Linux syslog,紀錄程式發報的錯誤訊息。
- 少用 multi-threading
- 不要寫出 debug mode 與 release mode 行為相異的程式:筆者曾經碰過 class data member 在 debug mode 時會被初始化為 0,但 release mode 則不會的 C++ 程式,花了很久的時間才找出問題。
- 避免有害作法:例如筆者之前發表過一篇「為何 Google 禁止工程師使用 C++ static object?」,這部份不難預防,參照 Google C++ Style Guide、好好把 Effective C++、C++ Gotchas 讀一讀可以預防大部分 C++ coding 陷阱。更進一步可以參考 Secure Coding in C and C++。
- 軟體版本附上 git SHA-1 hash code,以便出問題時可以 clone/reset 出對應的版本加以驗證。
事後治療
- 從專案啟動時就使用 valgrind + gdb,以 valgrind –track-fds --leak-check=full 清查記憶體有無正確存取。
- 交付軟體給 QA 測試時應該掛載 gdb,以便保證問題發生時能準確找到問題點。
- 基本的壓力測試、回歸測試、邊界測試不能省。能有單元測試當然更好。
- debug 優先新增功能。
事先預防勝過事後治療
筆者碰過很多次客戶的問題無法在公司重現,因為客戶的設備價格可能高達上百萬到上千萬,上面的 PLC、馬達、氣壓缸、變頻器...也不可能通通準備一套(大概沒有幾間公司有這種財力)。
就算準備了相同一整套設備,也不可能複製客戶環境的室溫、電壓、有無接地...
但如果能做好事先預防,至少可以排除大部分跟自己有關的問題 :)
就算準備了相同一整套設備,也不可能複製客戶環境的室溫、電壓、有無接地...
但如果能做好事先預防,至少可以排除大部分跟自己有關的問題 :)
硬體上的考量
充足的 Flash 空間
可能是因為成本考量,台灣人喜歡把硬體設計的剛剛好,這樣要跑 debug 版的程式就有困難了,也無法儲存 core dump。再說 gcc 以 debug 模式編譯出來的執行檔在尚未 strip 前非常大,而 strip 後就會遺失很多 symbol,gdb 就無法精確找到問題的發生點。
充足的記憶體空間
以 valgrind or gdb 跑應用肯定需要更多記憶體,如果把硬體設計的太剛好,要跑這些除錯軟體就有困難。至少要給 RD 一個記憶體與 Flash 較大的工程版硬體進行除錯測試。
保留 Serial Console
有些人比較喜歡 ssh,但產品可能沒有 Ethernet or Wi-Fi(我知道很扯,不過真的有),或者您正在找網路方面的問題,Serial Console 是最保險的。如果拿掉他,事後要用 top 檢查 CPU loading 或用 /proc/meminfo 觀察記憶體用量就很困難了,而且有了他就可以寫一些簡單的 script 測試軟體或用 tftp 指令下載部份 firmware 進行測試,如果只能依靠 GUI App,那就會浪費很多開發時間。
還記得電鍍廠的環境尤其可怕,連設備都被腐蝕了,連 debug 的心情都快沒了...0rz
真實故事
201x 年某週五筆者本來已經準備好下班,但業務大哥急電:「還在公司嗎?林口客戶發生問題,趕快來一趟!」於是筆者晚飯還沒吃就被拉到林口郊區工廠協助客人試車,弄到晚上 11 點半才拖著疲憊的身軀回到台北的家。而且好笑的是這些 bug 還不是我製造出來的...
也曾經被客人當面指責「不要把我們當白老鼠好嗎?」也曾耳聞客戶員工用了某家的產品,然後把設備撞壞被要求離職。也為了協助客人完成試車,吃客戶的員工餐廳吃到怕...(最慘的是最後客戶沒下單)
還記得電鍍廠的環境尤其可怕,連設備都被腐蝕了,連 debug 的心情都快沒了...0rz
心得
這些都是花了無數金錢人力得來的教訓,我還跟同事開玩笑說會不會剛好賺的錢都拿去付油錢差旅費了 XD。這些還不打緊,因為損失商譽才是最嚴重的,不是有人說「口碑比石碑堅硬持久?」希望大家能從筆者的經驗得到一點東西...:)
Hi 關於 valgrind如果沒辦法在嵌入式產品運作的話(因為曾經遇過CPU太舊無法支援),個人做法是把程式會控制硬體的底層function全部拿掉,直接透過x86 gcc complier編譯此程式之後,再透過x86上的valgrind檢查才知道這支程式的C++上層邏輯會造成memoary leak :(
回覆刪除因此結論是,可以透過剛才的方式,先測試你的上層邏輯是否有所錯誤(可以先把硬體的操作function先排除),提供參考。
感謝回應,我之前就是拿到x86上用valgrind檢查,不過現在傾向一種作法是乾脆拋棄C/C++改用Go解決memory leak的問題
刪除