iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 14
1

良好程式碼的優點大同小異。
不好的程式碼的糙點卻各有巧妙之處。

-- 台南原地方法院,最棒的古蹟修復案例之一。基本的從外觀的牆面油漆去除,到馬薩式屋頂的木構造修復。建築最美的雙重圓頂與大廳裝飾,都原汁原味的重現在現在的古蹟內。不只是外觀修復得很美,連內部的構造都依原本的構想,聽說是以零件抽離一件修復一件的方式修復,以確保正確性。也是台南唯一開放貓道,可以參觀馬薩式屋頂木構造的古蹟,長達八年的修復已完成,現在是台南司法博物館。

在說了什麼多的「不要這麼做」之後,偶爾也來寫一下「那要怎麼做」比較好。
這次花一點篇幅來介紹 function 怎麼寫,比較好。(好像語法工匠)
在《忍者》[1]第一版中,直接就指出 JavaScript 的 function 有 4 種

  1. 一般的 function
  2. method: 物件中的 function
  3. constructor: 建構物件的 function
  4. recursive: 呼叫自己的 function

(ES6 之後,加上的 arrow function ,請看《忍者2》)

高品質,就是要濃醇香

林鳳營?!不!程式也要濃醇香!!!

  • 濃: 高內聚力
  • 醇: 好命名與參數設計
  • 香: 沒有需要重構的壞味道

好的 function 能做些什麼事

  1. 自我文化化,讓你忘記實作
  2. 不重複你自己 (DRY = Don't repeat yourself)
  3. 封裝順序耦合性
  4. 封裝指標 (某些有指標的語言)
  5. 改善移殖性 (ex: POSIX[2])
  6. 封裝布林運算
  7. 找出無效之處
  8. 提高可測試性,提升可靠度
  9. 將 function 變短

好的程式具備非常多的優點。
相信把 function 寫好,幾乎就是把程式寫好一半了。

那開始介紹「如何把 function寫好」吧!

命名

怎麼做,才是 function 的好命名呢?
命名這一件事,除了程式碼品質的書有介紹,最近看了一本《資訊架構學》也有介紹呢!

其實,沒這麼難!

命名的目的,在於「好猜」。
猜得中你的實作,就不用看了!所以看 code 變快!

反之,命名命得不好,就不好猜。
對吧?所以命名的好壞,回歸到開發者是否可以正確的理解、表達問題。

使用數字命名

這真的是,詞窮的表現。

使用動詞,尤其是 methods

除非是建構式
function 指的是一個「動作」,所以要用動詞

尤其是用在 method 上,會更有 S + V 的文化感, S.V()
(S: 主詞,使用名詞,V: 動詞)

使用對應的名稱

引用自 mark9462 的鐵人文章: 易讀程式之美學系列 第 9 篇
不被誤解的名稱--2

  1. 包含邊界的極值優先使用 min 與 max[3]
  2. 閉區間優先使用 first 與 end
  3. 半開放區間優先使用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版)


上一篇
不依照語法寫 code
下一篇
如何寫高品質 function (輸出+輸入篇)
系列文
可不可以不要寫糙 code30

尚未有邦友留言

立即登入留言