Blog
Blog copied to clipboard
10 種實作 readable code 的方法
作者提出 10 種實作方法提升 code 的 readability.
- 選好一種 formatting rule, 之後想辦法讓它自動去做 format
- 消滅 dead code
- 打平 nested code
- 多用 class 包裝
- 不要有過長的 code block
- Coding 到一個段落之後, 再去想 naming
- 不要寫 comment
- Return 有意義的 value
- Rule of three, 重複 code 三次之前先留著
- Coding 要有對稱性 (一致性)
[name=Chaol Liu][time=20181108] derived from...
10 practices for readable code
jason.pureconcepts.net
[name=@gonedark] [time= September 18, 2018]
- 我至今已經 coding 20 年了. 這段時間參與過 17 個團隊, 用不同語言 coding, 建立了上百件專案. 專案從單純的 blog site, 到支援每秒 3,000 次 requests 的 APIs, 再到眾多暢銷 apps.
- 從這些經歷, 再與我讀過的書結合, 有一項對我來說, 是 coding 中最重要的事情: readability(可讀性)
- 表面上, readability 看似主觀. 是一種可能在不同語言, 不同 codebases, 不同團隊都會不一樣的東西. 但當你看得再更深一點, 會發現些能夠讓 code 變得 readable 的核心要素.
- 多數 PGs 都 too close to the computer. 如果 code 能 run, 其他都不重要. 雖然這很常見, 但這樣做抹除了所有 human elements.
- 過去幾個月, 我將這些要素提煉成 10 種實作, 讓你改善 readability 並降低 code 的複雜度. 我把詳細內容都寫在 BaseCode 上.
- 多數人認為這是小事, 太過基礎, 但我跟你保證, 我所遇過的 bad code 都沒辦法套用在這些實作上. 而 good code 只少能找到一個.
Formatting
- 浪費太多精力在 formatting 了. 用 tab 還是 space. 用 Allman 還是 K&R. 你最後會理解到 formatting 其實根本不重要. 採用一種標準的 format, 運用在 codebase, 再想辦法讓它自動做. 然後就可以把精力花在 code 上了.
// Allman
while (x == y)
{
something();
somethingelse();
}
// K&R
while (x == y) {
something();
somethingelse();
}
Dead code
- 所有註解的 code block, 沒用的變數, 還有 unreachable code 都是 dead code. 日復一日, 這些 dead code 最後會毀掉你的 codebase. 如同經典的 Broken Windows Theory(破窗理論) 一樣. 你必須找出, 然後消除.
Nested code
- 幾乎所有 code 的基礎都是邏輯. 我們寫 code 會 make decisions(做決定), iterations(迭代), 與 calculations(計算). 通常會在 branches 或 loops 中造成 nested block of code. 對電腦來說容易追蹤, 但對人來說不易. 要拆開 nested code 可以運用 guard clauses, early returns, 或是 functional programming 方面的技巧.
function submit() {
if (!validate()) // guard clause
return; // early return
// do submit
// ...
}
Using objects
- 雖然目前是 OOP 的時代, 我們還是會有 primitive obsession(基本型別偏執) 的情形. 會在以下所提之處發現, 一長串 parameter lists, data clump(資料泥團), 或是自訂的 array/dictionary 結構. 它們都能被 refactored 成 object. 這樣做不只讓 data 的結構形式化, 還能讓邏輯重複使用.
primitive obsession: 只用基本型別代表資料型別. 例如: 直接就用 double 宣告出一個 money 變數, 而不是做出一個 Money Class. data clump: 當 2 或 2 以上個變數總是同時用到, 如果只使用其中一個會不合理. 例如: 專案裡所有處理 money 的函式除了 money 金額(double)以外, 都還需要一個 money 幣別(enum).
Big Blocks
- 如果我沒有限制自己的 code block 長度, 可能會無窮無盡地寫下去. 當你確定你有一個 big block of code 時, 就有可以對 code 做些 recognize, regroup 與 refactor. 這些簡單的過程讓你決定出 code block 的 context 與 abstraction level, 你就能正確辨別出 code block 所屬責任, 然後再做 refactor, 讓 code block 變得更加 readable, 變得較不複雜.
Naming
- 當然, 命名很難. 有一個小技巧, 叫 naming-deferral(延遲命名). 就是 coding 時不要卡在命名上. 繼續 coding. 如果必要, 就先隨便命名. 然後繼續 coding. 我保證你完成功能, 就會想出一個適合的名字了.
Removing Comments
- 這項實作對我來說, 就像是改變遊戲規則一樣(過去都教導要多做註解). 也是它讓我開始專注 readability. 就算我盡力解釋, 還是會有至少一人不接受. 幾乎所有情況, 你要讓它完全不需要註解.
Reasonable Returns
- 我們會回傳奇怪的值. 尤其是邊界值. 像是 -1 或 684 或 null. 反過來說, 你就需要很多 code 來處理這種值. 實際上, null 的創始者稱 null 是 The Billion Dollar Mistake(十億美金的錯誤). 你應該要回傳更有意義的值. 理想是要讓呼叫端, 就算是走到 negative path 也能夠處理. 如果真的有例外發生, 也會有比用 null 溝通更適合的方法.
Rule of Three
- 想一個數列. 我會提供一個數字是 2, 然後問你下一個是?. 可能是 3 或 4, 也可能是 1 或 2.1. 事實是你不知道. 所以我提供另一個數字 4, 也就是現在你所知的數列是 2, 4. 問你下一個是? 可能是 6 或 8 或 16. 就算我們對可能的答案更加有信心了, 但還是不確定. 現在我提供給你 2, 4, 16. 問你下一個是? 現在有三個資料, 身為 PG, 看出是前一個值的平方數列, 確定下一個數字會是 256. 這就是 Rule of Three(三次法則).
- 這個範例展示出, 我們不需要提前決定 abstraction 或是 design 因而分心. The Rule of Three 就是延遲處理, 直到我們有更多資訊供我們做出正確的決定. Sandi Metz 說過, "duplication is far cheaper than the wrong abstraction(重複 coding 遠比 abstraction 錯誤耗費更低成本)."
Symmetry
- 現在剩最後一項實作, 要讓 code 持續觸動近乎詩意的 readability -- symmetry(對稱). 這取自 Kent Beck 的 Implementation Patterns
Symmetry in code is where the same idea is expressed the same way everywhere it appears. (code 的 symmetry 就是相同想法以相同方式擴散到任何該出現的地方)
- 嘴上說比達成簡單. Symmetry 體現出寫作創意. 它是許多實作的基礎: naming, structure, objects, patterns. 它可能因語言而異, 因 codebase 而異, 因團隊而異.