# Martin Fowler 的重點 ###### tags: `software developement` 當我們在看哪段程式碼需要被重構時, 這類需要被重構的函式通常隱藏一些不太好的習慣, 在程式領域被稱作 Code Smell。 通常第一眼會先看那個函式很長, 當你可以將程式切小塊,並為他取個好的名字, 這會讓你的工作事半功倍。 但我們所謂的好的函式,並非是看他的精簡程度, 有的時候甚至函式命名比實作細節還要長都會是好的函式, 而是取決於函式的內容,函式的意圖, 一個好的命名可以告訴閱讀者這段程式碼明確的意圖, 而不需要去看他的實作細節, 這就是一段好的程式碼。 ## Refactor Tip ### 拆函式 Extract Function (Extract Method) 這是一個簡單又快速重構程式碼的技巧 > 每個重構就是一小段一小段的改變 > 這一小段的改變小到甚至不值得去改它 > 但這樣的小段改變累積起來後 > 就會變成很可觀的改變 > 重構就是改寫你的程式碼 > 讓你的程式碼更易於理解 > 但不改變原本應有的行為 > 判別一個好的程式碼命名 > 就是你只需要看到名字就知道他是拿來做什麼的 > 而不需要去看他的實作細節 ### 重新命名變數 Rename Variable 編程習慣 (Coding Convention) 變數的命名除了有自己的編程習慣之外, 也要注意團隊的編程習慣。 Martin Fowler 個人的一個變數命名習慣是, 他喜歡用型別來命名變數, 這是來自於 SmallTalk 的編程習慣。 ### Replace Temp with Query 將暫時性的變數替換成Query函式 ```diff - const play = plays[aPerformance.playID]; + const play = playFor(perf); + function playFor(aPerformance) { + return plays[aPerformance.playID]; + } ``` ### Inline Variable 用 Function Call 取代暫時性的變數 ```js const play = playFor(perf); let thisAmount = amountFor(perf, play); ``` ```diff - const play = playFor(perf); + let thisAmount = amountFor(perf, playFor(perf)); ``` Martin 提到這個可能會有人覺得不習慣, 可能的原因是 **重複執行函式多次**, 重複執行函式多次 可能會有的問題是 - 函式有 Side Effect 那會產生問題, 但若函式沒有 Side Effect,就沒有問題。 Martin 提到盡可能讓函式沒有 Side Effect。 - 效能。 Martin 解釋,真正要解決效能問題並非是透過這小段的程式碼, 而是要透過 Profiling 去測試效能, 並且找到真正效能發生的問題點, 如果沒有透過測量來斷定效能,就是在亂猜而已, 而就我們的經驗,這段並不會對效能產生影響。 ### Change Function Declaration 少的 Function Arguments 優於多的 Function Arguments > Comment 很多並不好, > 反而表示你的程式碼太過於複雜,需要這麼多 Comment, > 一段好的程式碼會告訴你這段在寫什麼,而非 Comment。 ### Split Loop 不要將事情都並在同個 Loop 做, 根據目的將 Loop 拆解。 ### Slide Statements 將變數移動到鄰近需要使用的地方, 而非遠在天邊的最上頭。 ### Split Phase 將程式分析後,拆分步驟, 資料 => 計算 => 輸出 ## 提問 ### Q.請問 重構 的主要目的是什麼 重構的主要目的是讓程式碼,易於理解易於修改。 而易於理解易於修改的目的是為了可以讓新功能的發布更加快速。 其背後的目的是 商業原因, 電腦並不在意你的程式碼美不美, 客戶不會 **直接** 在意你的程式碼美不美, 但客戶 **會** 在意我們增加新功能的速度。 每當我們要做新的功能時, 都必須去理解某些程式碼片段, 所以做重構的意圖是, 我們希望最小化我們理解跟調整程式碼所需要花費的成本, 將函式切分後,我們只需要理解一小部分的程式碼,而非整個叢林。 重構能帶給企業是 - 減少人力,時間成本, - 更快速的產出 重構是為了企業跟你自己 ### Q.通常一段新的程式碼會在什麼時間點重構 Martin 說如果他正在編寫的新的功能,五分鐘內就會進行重構, 實際上這就是所謂的 TDD Cycle。