如何寫高品質 function (命名+參數篇)
良好程式碼的優點大同小異。
不好的程式碼的糙點卻各有巧妙之處。

– 台南原地方法院,最棒的古蹟修復案例之一。基本的從外觀的牆面油漆去除,到馬薩式屋頂的木構造修復。建築最美的雙重圓頂與大廳裝飾,都原汁原味的重現在現在的古蹟內。不只是外觀修復得很美,連內部的構造都依原本的構想,聽說是以零件抽離一件修復一件的方式修復,以確保正確性。也是台南唯一開放貓道,可以參觀馬薩式屋頂木構造的古蹟,長達八年的修復已完成,現在是台南司法博物館。
在說了什麼多的「不要這麼做」之後,偶爾也來寫一下「那要怎麼做」比較好。
這次花一點篇幅來介紹 function 怎麼寫,比較好。(好像語法工匠)
在《忍者》[1]第一版中,直接就指出 JavaScript 的 function 有 4 種
- 一般的 function
- method: 物件中的 function
- constructor: 建構物件的 function
- recursive: 呼叫自己的 function
(ES6 之後,加上的 arrow function ,請看《忍者2》)
¶高品質,就是要濃醇香
林鳳營?!不!程式也要濃醇香!!!
- 濃: 高內聚力
- 醇: 好命名與參數設計
- 香: 沒有需要重構的壞味道
好的 function 能做些什麼事
- 自我文化化,讓你忘記實作
- 不重複你自己 (DRY = Don’t repeat yourself)
- 封裝順序耦合性
- 封裝指標 (某些有指標的語言)
- 改善移殖性 (ex: POSIX[2])
- 封裝布林運算
- 找出無效之處
- 提高可測試性,提升可靠度
- 將 function 變短
好的程式具備非常多的優點。
相信把 function 寫好,幾乎就是把程式寫好一半了。
那開始介紹「如何把 function寫好」吧!
¶命名
怎麼做,才是 function 的好命名呢?
命名這一件事,除了程式碼品質的書有介紹,最近看了一本《資訊架構學》也有介紹呢!
其實,沒這麼難!
命名的目的,在於「好猜」。
猜得中你的實作,就不用看了!所以看 code 變快!
反之,命名命得不好,就不好猜。
對吧?所以命名的好壞,回歸到開發者是否可以正確的理解、表達問題。
¶使用數字命名
這真的是,詞窮的表現。
¶使用動詞,尤其是 methods
除非是建構式
function 指的是一個「動作」,所以要用動詞
尤其是用在 method 上,會更有 S + V 的文化感, S.V()
(S: 主詞,使用名詞,V: 動詞)
¶使用對應的名稱
引用自 mark9462 的鐵人文章: 易讀程式之美學系列 第 9 篇
不被誤解的名稱–2
- 包含邊界的極值優先使用 min 與 max[3]
- 閉區間優先使用 first 與 end
- 半開放區間優先使用begin與end
用區間方式建立命名默契是個不錯的方式
也有一些已經實作的方式
C++
vectorInt.begin();
vectorInt.end();
vectorInt.push();
vectorInt.pull();
JavaScript
array.push();
array.pull();
array.shift();
array.unshift(); //這就很不相對
¶參數
在這裡,要介紹一下 argument 和 parameter 的定義
- argument 指的是參數值
- parameter 指的是參數變數
js 的 arguments 物件,主要是用來取得「值」。
¶位置對應 (尤其是類似作用的情況)
《設計的心理學》[4] 有提到一個「對應」的概念,大致上是說: 如果設計有考慮「位置與功能的對應」就會降低心理負擔
在 JavaScript 中的 Array methods 可以看到這一個默契
Array.prototype.map((item, index, array) => {})
Array.prototype.sort((item, index, array) => {})
Array.prototype.forEach((item, index, array) => {})
在 jQuery 中的 methods 也可以看見類似的效果
jQuery.map((index, item) => {});
jQuery.forEach((index, item) => {});
¶輸入/輸出
可以有依輸出輸出進行排序
也可以加上前綴,提醒使用者參數是屬於輸入還是輸出。
看一段硬體描述語言的寫法
module mux (out, select, in0, in1, in2, in3);
endmodule
module adder (oSum, iEnable, iAddend0, iAddend1);
endmodule
¶其它
還有很多要注意的參數設計重點,在此就直接列出重點
- 全部參數都要使用,不用的參數,就不列出來。
- 表示函數執行的狀態或錯誤的參數,要放在相同的位置 (通常是最後)
- 可以的話數量掌握在 7±2 的範圍
¶參考資料
[1]: 忍者:JavaScript開發技巧探秘
[2]: 可移植作業系統埠
[3]: 《程式碼易讀之美學》Ch3 不被誤解的名稱
[4]: 設計的心理學:人性化的產品設計如何改變世界(3版)