❀ 前言 ❀

最近看了很多關於程式設計的觀念與資料,
雖然我現在不是什麼知名的工程師,
但在目前的專案裡,很多時候擴充到後面都會變得不知所措,
要好好設計,對我來說真的很有感。

喔對了,本篇文章參考至【Clean Code 無瑕的程式碼】
裡面還有更多的程式設計技巧
有興趣的讀者不妨自行借閱來翻翻~

❀ 正題 ❀

*以下出現範例以python為主*
關於命名,看似枝微末節的小事,實際上對於開發有極大的影響。
畢竟一旦命下去,就會被頻繁的使用,
因此我認為一個好的命名,應當包括以下要素:

  • 一目了然
  • 統一字詞

必須一目了然

一個神祕又懶惰的魔法師,最喜歡用的就是速速來!魔法,
只要被他的魔法標籤紀錄,就能使用速速來!xxx召喚該物。
然而他懶到不想念太長的名字,因此他寫了一張清單,上面寫著:

a => 糖果罐 b => 空罐子 c => 積木

以便對照,現在他只需要喊出速速來!a就能找到糖果罐。

一天又一天過去了,他的清單也不斷增長,
然而好景不常,某天他弄丟了他的清單,
更糟的是,他忘了那些編號…
結果就是,他只能自己跑去櫃子確認要得東西了。
—————————————————————————–
是的,我們不應用看不懂的名字為變數命名
即便有使用註解解釋該變數的作用
但一個好的變數命名,其實不需要說明就能知道要幹什麼
變數不必擔心長,而要擔心看不懂
如果怕每次都要打很長麻煩,tab 就能解決一切了ouo

拿我自己專案中的傷害計算為例,
這邊的a就不會是個好變數

可以用 randomNumber 代替
(這邊我當時的想法是,阿反正也只會用在這,那就亂取名ㄅ:p)
—————————————————————————–
於是乎,這名法師決定重新標記,以下是他的命名法則

雖然每個看起來都明確些了,卻沒有切入要點…
導致他還是搞不清楚究竟誰是誰
—————————————————————————–
這就像是以下這段程式碼

1
2
3
4
5
6
def getNumber():
list1 = []
for i in theList:
if i["effect"] == 3:
list1.append(i)
return list1

跟這一段程式碼

1
2
3
4
5
6
def getPoisonedPeople():
poisonedPeople = []
for player in players:
if player["effect"] == POISON:
poisonedPeople.append(i)
return poisonedPeople

原來是要找出中毒的人
是不是能很明顯地感覺到程式碼會講話呢
一個恰當的命名,能讓人們迅速理解發生了什麼事

最好統一字詞

可憐的法師已經吃盡了苦頭,他打消了偷懶的念頭,
將每個東西都清楚的一一標出。
原先以為能一勞永逸,當他喊出速速來!糖果瓶時…
…什麼都沒發生。
而當他氣沖沖地走向櫃子,才發現

啊哈!原來叫做糖果罐呀…
—————————————————————————–
是的,我們應該找出我們自己(或開發團隊)習慣的字詞
並且約定好之後都統一使用該字詞去定義相同類別變數
好比我在一個專案中的Player有一個屬性speed
然而Enemy中相同意義屬性卻叫Agi
這著實讓我在後期開發吃了不少苦頭,得不斷的查詢該物件有的屬性究竟是speed抑或Agi

此外我們也應該避免無意義的字詞
像是thea等等冠詞
永遠不會有人能分辨出theListaListlist的差異
這其實就跟list1list2list3是差不多的意思

補充 - 類別、方法的命名淺規則

類別(Class)

一個類別通常使用名詞、名詞片語命名,並避免使用動詞
並且開頭通常為大寫。
例如:PlayerAnimalParent

方法(Function)

一個類別通常使用動詞、動詞片語
且常用字詞為get(提取值)、set(設定值)、is(判定)
例如:getPositionsetHpisMoving

❀ 後話 ❀

多虧這次教訓,這名法師總算理解到正確的命名是怎麼回事了
因此他也能精確而迅速地找到自己要的目標
真是可喜可賀皆大歡喜!

命名其實還有很多東西可以說
像是避免雙關、小聰明等等
命名法也有很多,如:小駝峰命名(Camel case)、大駝峰命名(Pascal Case)、底線命名法(Snake case)
或者一些走入歷史的命名法,如:匈牙利標誌法、成員字首等等
這邊只是寫出我比較有感的,若讀者有興趣,也能查查看
最重要的是找到自己習慣的命名法則,讓自己在之後開發能事半功倍!