iT邦幫忙

DAY 1
9

如何提升系統設計品質 - 技術與工具以.NET為例系列 第 1

[如何提升系統品質-Day1]命名的重要性

好的命名讓你上天堂,壞的命名讓你住套房。
誰都寫得出機器看的懂的程式碼,但好的程式碼是讓人可以輕易看懂的。

這篇文章以Clean Code這本書中,提到的Meaningful Names應該要注意哪些地方來供各位當個參考。

在這篇文章開始之前,要先提出一個重要的觀念,雖然好的Naming很重要,但還有一個rule比這重要,就是一致性。如果今天是針對已經存在的系統要附加新的功能或是修改舊的程式,那麼『一致性』要比新的Naming rule重要!在導入新的coding style時,一定要謹慎的審視是否會導致現有系統在閱讀上的障礙,導致後續團隊開發時無所適從。

[如何提升系統品質]系列文章連結
1.Use Intention-Revealing Names:透過命名就能淺而易見其意圖
如果一個命名,還需要註解來解釋它,就代表他還不夠清楚表示意思。
(1)不好的例子:

int d; // elapsed time in days 

(2)好的例子:

int elapsedTimeInDays; 
int daysSinceCreation; 
int daysSinceModification; 
int fileAgeInDays; 

2.Avoid Disinformation:避免誤導
(1)不要使用特殊或多重意義的縮寫
(2)避免使用具有特殊意義的關鍵字命名
例如:accountList,因為List是關鍵字,所以可以取成accounts或accountGroup。
(3)避免兩個命名太長且太相像
您能看得出來這兩個的差異嗎?
XYZControllerForEfficientHandlingOfStrings
XYZControllerForEfficientStorageOfStrings
應該將贅字移除。
(4)代表同樣意思、同一件事、同一個東西時,命名應該一致(可透過glossary來統一)
(5)避免1與L的差異,0與O的差異
例如:

int a = l; 
if ( O == l ) 
a = O1; 
else 
l = 01; 

3.Make Meaningful Distinctions
獨自開發時容易因為一時的方便,只為了建置或開發方便,而隨手使用了不具意義或暫時的命名,往往之後帶來相當多潛在的問題。
(1)避免Number-series naming
例如:

public static void copyChars(char a1[], char a2[]) { 
   for (int i = 0; i < a1.length; i++) { 
     a2[i] = a1[i]; 
   } 
} 

(2)避免用不同字眼代表同一件事,例如info與data,或是a, an, the的差異
(3)避免贅字
例如以下的程式碼,會造成閱讀的人產生疑惑,這三個function有什麼差異:

getActiveAccount(); 
getActiveAccounts(); 
getActiveAccountInfo();

4.Use Pronounceable Names,使用可以發音的Name,可以幫助溝通,溝通時比較不會彆扭,不會顯得愚蠢。
(1)無法發音的Naming

class DtaRcrd102 { 
private Date genymdhms; 
private Date modymdhms; 
private final String pszqint = "102"; 
}; 

(2)轉換成可以發音的Naming

class Customer { 
private Date generationTimestamp; 
private Date modificationTimestamp;; 
private final String recordId = "102"; 
/* ... */ 
}; 

5.Use Searchable Names,當需要尋找時,找不到真的是欲哭無淚。
(1)避免用數字與單一字母命名,可改採用constant或Enum賦予意義。單一字母的命名,最多只允許在很短的迴圈或method中使用。
(2)longer names比shorter names好,至少搜尋容易定位
(3)很難搜尋的code:

for (int j=0; j<34; j++) { 
s += (t[j]*4)/5; 
} 

(4)轉換後的code:

int realDaysPerIdealDay = 4; 
const int WORK_DAYS_PER_WEEK = 5; 
int sum = 0; 
for (int j=0; j < NUMBER_OF_TASKS; j++) { 
int realTaskDays = taskEstimate[j] * realDaysPerIdealDay; 
int realTaskWeeks = (realdays / WORK_DAYS_PER_WEEK); 
sum += realTaskWeeks; 
} 

6.Avoid Encodings,避免自行定義特殊的編碼命名規則,會增加維護上的困難跟training成本
(1)編碼命名方式,會導致正常人都無法瞭解該命名意義:
例如class名稱命成:RGB001_256A

7.Hungarian Notation,匈牙利命名法有其時代背景的需求,但現在的IDE工具進步許多,理應避免這樣的避免方式。
(1)由來
Fortran開始使用first letter for the type,也就是匈牙利命名法
在C的時代,compiler不會幫忙檢查 type,所以HN是有意義的
(2)class跟function只負責單一功能,要能一眼看出來每一個變數的意義,加上型別prefix只是贅字
(3)不再需要type encoding ,加上type反而導致未來修改型別時,需要改更多的命名,否則將導致bug
例子

PhoneNumber phoneString; 
// name not changed when type changed!

8.Member Prefixes,同上,IDE工具可以讓我們快速找到該變數的定義,不需要再透過前置詞來表示該變數是區域、全域或屬性
(1)不好的例子:

(2)轉換後的例子:

9.類別名稱使用單數名詞,function名稱使用動詞。

10.Don't Be Cute,不要在Naming上搞笑,可能導致只有自己懂笑點,而別人搞不懂這個東西是什麼。盡量用白話、常見的term命名,不要用文言文,或俚語。

11.Don't Pun,不要用雙關語。一語雙關,會導致讓讀者有猜測的空間,或需要玩猜猜看。

12.Don't Add Gratuitous Context,每個東西命名若都加上application或class的prefix,反而造成每個term都有,那就多餘了。最常見在DB Table的欄位命名,或是類別的屬性命名。

結論:
不要害怕rename,現在的現在的IDE重構工具都相當方便使用,持續使用refactoring tool 改善命名,只需要花一點小時間就可以省下以後一長段時間。當然,還是有個重要的前提:『重新命名之前,要確認是否已經公開給外界使用,若已經有外部服務相依於此命名,那麼不要輕易的更動這個命名』

Question:
您能找出下面這段程式碼,有哪些問題嗎?


下一篇
[如何提升系統品質-Day2]重構– UI, Business logic, Data access概念分開
系列文
如何提升系統設計品質 - 技術與工具以.NET為例30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
BeEvil_Y
iT邦新手 4 級 ‧ 2020-03-07 17:58:24

我其實搞不太懂你們整天「討論」前後人程式維護難易度是要做什麼??
他又不是你的爸爸媽媽,有什麼義務寫到讓你能改?

而且a1的命名只是增加維護難度而已
跟你一串名字比起來,省了快一半的記憶體。

臉書、谷歌、矽谷他們的程式,大部份也都給他「亂碼」化了。
亂碼後的變數名稱也都沒超過10個字元。

事實擺明

1.我們沒有義務讓別人能輕輕鬆鬆懂我們的程式
2.如有需要,我們可以使其複雜化,在沒有增加伺服器負擔的情況下。
3.命名都要亂碼化,除非給自已看,不然沒意義。

給外部的可以訪照現實
建立「機場」、「港口」就好。

他們的機能就是檢測出入口、資料的核對與加密。

而且,我看了你不少串的這系列文章。
我可以跟你講

你的文章也需要重構。
沒有起承轉合,也沒有H1、H2、H3做好標題的分類「大、中、小」。
就算這網站不支援,你一樣可以用縮排達到目地。

你用這麼不適閱讀的方式,來講解程式重構,給看文的人感受其說服力真的有待加強。

我要留言

立即登入留言