Blog icon indicating copy to clipboard operation
Blog copied to clipboard

10 種實作 readable code 的方法

Open ChaoLiou opened this issue 6 years ago • 0 comments

作者提出 10 種實作方法提升 code 的 readability.

  1. 選好一種 formatting rule, 之後想辦法讓它自動去做 format
  2. 消滅 dead code
  3. 打平 nested code
  4. 多用 class 包裝
  5. 不要有過長的 code block
  6. Coding 到一個段落之後, 再去想 naming
  7. 不要寫 comment
  8. Return 有意義的 value
  9. Rule of three, 重複 code 三次之前先留著
  10. 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 而異, 因團隊而異.

ChaoLiou avatar Nov 08 '18 08:11 ChaoLiou