看爛 Code 也是種學習
不知道是天生體質還是氣場異於常人,為什麼經常遇到公司要求我去重構專案。你可能會想,很棒啊!公司願意重構程式讓它變成自己想要的樣子不好嗎?但通常這種重構是「有前提條件」的,並不是很舒服的那種。
看過夠多糟糕的寫法,才知道好壞差在哪
工程師們有個很怪的特性,永遠覺得自己寫的很好讀,別人寫的很難讀。看過許多糟糕的寫法後,很多時候其實更能去體諒它人在寫程式時的感受。加上平時自己就有閱讀各大知名開源原始碼的習慣,比較過數種寫法的優劣,真正感受到好與壞的差別。
重構時痛出來的九條原則
有一些原則是我感受到非常重要的,這些原則其實可以幫助你寫出別人「更容易看懂」的程式。
- 不要去用字串組合「不是動態的字串」,用常數來取代固定字串,不但在 IDE 反查更為容易,也好理解字串本身的含義,避免為工程化而寫效益不大的迴圈去組裝。
- 減少耦合的套件與模組,特別是Map、enum、i18n 這類的模組共用,採用注入或註冊的方式宣告。可以減少對程式的依賴理解難度,並更易於解耦。並不是極高的去共用元件就是好的工程設計,而是依據功能模組去有效分類管理,同時具備模組易於拆分理解才是好的共用。
- 減少狀態管理,除非有效能瓶頸,結果能用算的就不要去記憶「狀態」,減少狀態的資料結構複雜度。舉例,篩選結果盡量是當下計算而非記憶成新的集合或陣列,要紀錄成狀態的是篩選條件。
- 避免使用巢狀迴圈和巢狀判斷。避免並不是不行,要考慮到的是當巢狀寫的時候是不是更容易讓別人看出流程與順序,而不是要把要做的流程全部進行閱讀。除了巢狀邏輯,也避免在一行程式碼中放進超過3個邏輯閘。
- 流程操作不要封裝在函數式中的使用函式。流程盡量可以在最外層的 function 一覽全部的行為與執行分配。而非用 function 去引用 function 一層層往深層封裝。
- 避免業務關聯性縮寫。除了一些比較能夠被大眾接受的,比如: val, req, res, cb, fn, el 這類的縮寫。避免去設計獨特的縮寫舉例像是: project name > pn , selling price > sp , activity > act … 這類業務關聯性的縮寫。
- 有一種說法是不要有過多的註解,用好的命名與流程雖然足以傳達好的程式邏輯。但不要對自己太有自信,如果沒有經過足夠的驗證和 code review,註解絕對贏過沒有註解。
- 減少全域變數或全域註冊的操作模式。這種設計可以說是超級「方便」,不過如果專案規模達到一定的效果會非常難以尋找來源,若非有足夠的文件或規範支撐,否則避免採用這樣的操作。
- Linter 很重要很重要很重要!!!這個可能對於很多人來說是基本,但真的很多人因為弄不懂 lint 的規範與規則,任意去 disabled 規則,這絕對是大忌!
以上種種列舉其實也有蠻多 clear code 的既視感,但都是我在重構專案時真真切切痛過的經驗,有些敘述可能沒有 code 比較難理解,可能有時間再寫個部落格來上個範例。