# # 虎年行大運 ~ Clean Code 系列 - 有意義的命名 ## 【前言】 最近開始看 Clean Code 了,接下來會做關於書中內容的心得與個人經驗整理的分享文。 ## 【主文】 寫程式最重要的小事,那就是對程式碼的撰寫,程式碼中又充斥著許多物件的搭配使用與邏輯整頓,因此說**命名**是最重要的小事,一點也不為過。 **好的命名帶工程師上天堂、壞的命名帶工程師入茅房** 這句話一點不假,有個幾年歷練的熟手應該都知道好的命名會加速整體程式的閱讀、清晰思考路徑、完善邏輯的設計等等。然而命名這件事情從來都沒有一個白紙黑字寫好的規範教你如何做。 所以 Kai 希望能夠建立一套潛意識的思考方式,讓各位讀者在面對命名這件事情能以很自然的方式給出最好的名稱。 在不熟的時期蒙混著開發就會寫出了許多髒Code,加速累積程式債,最後面對一坨東西無從下手,產出與時間的比率指數性下滑,整個系統雪崩無法再開發,又要花費心血重建一套新系統。 又或者,你從沒看過任何關於命名的心得分享文、或是 Clean Code 這本書,而是憑藉著自己幾多年來打磨而成的經驗,在職場上大殺四方,那...其實還是推薦你看一下XD 原因無他,這種沒有規範的東西,看了就漲一點知識,好知識不漲嗎? 而 Kai 接下來要分享的也是累積的開發經驗與書中的部分內容理解後反芻的回饋。 ## 【書中的大道至簡】 遵循以下幾個方向或目標可以幫助工程師在命名這件事情上達到清晰的效果 - 精確名稱、代表事務或意圖相符 ```java= String name = "Kai"; // 較容易理解 String str = "Kai"; // 無法一眼明瞭 int age = 20; // 較容易理解 int a = 20; // ?? public String getName(){...} // 較容易理解 public String getStr(){...} // WTF is this? public int getAge(){...} // 較容易理解 public int getA(){...} // Enough!! ``` > 不限於業界專有名詞,如交易用的 QTY (Quantity) 表示數量 - 名稱之間避免模糊、應做有意義的區別 ```java= String name = "Kai"; public Student getStudent(){...} public String getStudentName(){...} public String getName(){...} // 你也許可以一眼明瞭第一個方法會回傳 Student 物件 // 但第二個和第三個方法就會懷疑是否有不同回傳值了,不論實際上是否回傳相同東西 ``` - 避免誤導 ```java= String nameMap [] = new String [10]; List nameArray = new LinkedList(10); Map<Stirng, String> nameList = new HashMap<String, Stirng>(); // 到底是 List, Array 還是 Map ?? ``` - 數值或字串作屬性化,方便查找 ```java= if(number > 10){...} // 你必須到這裡才可以找到 10 這個數字 int minNumber = 10; // 你可以使用 minNumber 的名稱或者數字 10 進行查找 if(number > minNumber){...} ``` - 設計能夠唸出的名稱 ```java= String studentName = "Kai"; // Student Name. Kai String sName = "Kai"; // S ?? Name Kai ?? ``` - 少做名稱編碼 ```java= 匈牙利標誌法... // 後省略一萬字 // 範例一 String studentName; int studentAge; // 範例二 String stu_name; // 自行把 student 編成 stu,增加識別困難與維護上手曲線 int stu_age; String name; // 比起上述,因為都包含在 Student 物件中的關係,不需要加上物件前綴詞 int age; // 因此屬性名稱看起來簡單易懂 ``` > 若還是害怕在開發中與其他物件搞混的話,應透過 IDE 的字符顏色的區別協助完善這類狀況,因為過多為了編碼的前後綴會讓名稱變得冗長和複雜 - 介面和實作的區別 (可類推抽象) ```java= interface Factory {...} // 建議 interface IFactory {...} // 已經有 class 協助分明了,不須再使用前綴詞 I class FactoryImpl {...} // 建議 class IFactoryImpl {...} // 已經有 class 協助分明了,不須再使用前綴詞 I ``` > 書中尚包含作者私心不想讓使用者知道自己給出的是一個介面,其實對 Kai 在開發上來說那個 I 真的是廢話... - 避免思維轉換 ```java= // 先看這一組屬性名稱 10 秒 String name1 = "Kai"; String name2 = "MyFather"; String name3 = "MyMonther"; int age1 = 20; int age2 = 50; int age3 = 60; // 在看這一組屬性名稱 10 秒 String name = "Kai"; String fatherName = "MyFather"; String motherName = "MyMonther"; int age = 20; int fatherAge = 50; int motherAge = 60; // 計算一下到看懂的時間花了多久? 而又能記住這些規則多久? // 半年後看到這個物件,會記得屬性的用途嗎? // 簡單問問自己就能懂了~ ``` - 同一種概念使用同一個字詞 ```java= public void addNumber(int number){...} public void provideMax(int max){...} public void deliverMin(int min){...} public String getCompareResult(){...} // 如果我跟你說這只是一個輸入上、下限後,再輸入一個值做數值比較的物件 // 你是不是會覺得輸入數值的那三個方法很難懂呢? public void setNumber(int number){...} public void setMax(int max){...} public void setMin(int min){...} public String getCompareResult(){...} // 這樣是不是清爽一些了? package.Admin.Page.page1; package.Admin.View.view2; package.Admin.Panel.panel3; package.Admin.Frame.frame4; // 上述存放的物件如果都是畫面的話,請盡可能整頓在一起 package.AdminPage.page1; package.AdminPage.page2; package.AdminPage.page3; package.AdminPage.page4; // 這樣是不是清爽一些了? ``` - 不使用雙關語的字詞 ```java= public void addString(String string){ this.nameList.add(string); } public void addString(String string, String string2){ string += string2; } // 你不該讓 add 同時表示 "添加" 與 "組合" 的意思 ``` - 有意義的前、後綴詞 ```java= String studentClassFieldNameWithoutSurname = "Kai"; // 過分強調了物件、類別屬性、無姓氏等部分 String studentName = "Kai"; // 不是推崇,但相比上述,student 這個前綴至少有物件強調意義 ``` ### 【類別和方法命名】 **類別** - 盡量使用名詞、專名等方式代表 - 首字大寫 - 單一字詞或少數字詞組成 **方法** - 盡量使用動詞、動詞片語,後加上特定名詞等方式代表 - 首字小寫 - 最少一個動詞 + 一個名詞的方式呈現其用途 - 有許多業界常用的字詞可以當作優先選擇 - get: 取得、取出 - set: 賦予、修改 - add: 增加、增添 - remove: 排除 - is: 判定 - do: 執行邏輯 - save: 儲存 (與DB操作較相關) - update: 修正、更新 (與DB操作較相關) - delete: 刪除、排除 (與DB操作較相關) ### 【解決方案領域和問題方案領域命名】 如果有機會讓他人看到你的程式碼,那這個人高機率也會是一名工程師,請盡量使用在電腦科學領域、資訊領域方面的專有名詞,如: 演算法、資料結構等等。 跨程式語言的障礙只應該存在於那些不熟悉的處理邏輯和變數上的使用,而不應該是在程式債。 ```java= List nameList = new ArrayList<String>(); // 從 SWIFT 跨來 Java 語言的人可能看不懂 ArrayList 是什麼? 為何需要寫 <String>? // 但他應該要能懂這是一個放置多個名稱的集合 ``` 然而,總是有些情況非常極端,那就不得不用處理的問題本身當作命名的依據了,盡量追求言簡意賅以達到容易閱讀的效果。 例如: 因儲存空間的關係,必須每天清除相隔3天以上的 Log 檔案 ``` private void removeLogApart3Days(){...} ``` ## 【駝峰 & 符號 & 符號區隔】 **駝峰** - 駝峰式命名基本上算是業界的標準規範,主要在於清晰名稱中的每一個字詞用。 **符號** - 基本上,已經很少人會使用符號當作命名素材,無論是主詞、前綴、後綴都一樣,這是因為符號完全無法幫助識別,更甚的是與邏輯運算子衝突造成錯誤判讀的可能。 **符號區隔** - 比直接使用符號好一些,還有不少應用場景,但是 Kai 推薦一律使用駝峰式命名法,當然在一些地方會有意想不到的效果,如: ENUM 類的物件命名用符號區隔就是一個很大的加分 (再加上全大寫就更好了XD) ## 【動詞優先於名詞】 比較常用於方法的命名,採用同英文的語言邏輯,先動詞再名詞,可以完整強調一個事務的進行或用途。 這是因為方法通常是為了處理一個動作,以動作為開頭就會讓人感到十分自然。 又一種說法是在寫程式之前,應該都會先學基本的英文,動詞在前的做法是為了與英文語意的邏輯一致的習慣,避免寫起來綁手綁腳。 ```java= public void setNumber(int number){...} // 較容易識別 public void numberSet(int number){...} // 較難識別 ``` ## 【結語】 以上就是結合個人經驗與書中提到的整理,重點是這不代表一切! 這些不是必須遵守的規範! 只是說依循這些法則可以讓程式碼的命名變得更好。 這些並非一蹴可幾,必須按部就班的在各種嘗試中獲得經驗,相信累積下來的成長絕對可觀! 也或許哪一天面對的環境狀況完全不適用也說不定...哈~ 首頁 [Kai 個人技術 Hackmd](/2G-RoB0QTrKzkftH2uLueA) ###### tags: `Clean Code 無瑕的程式碼`
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up