編碼之道:取個好名字很重要

11 February 2015

代碼就是程序員的孩子,給「孩子」取個好聽的名字很重要!c++

咱們在項目開發中,接觸到的變量、函數、類多數都是項目本身定義的,每每都是爲了解決一些特定的領域的問題,引入了各類各樣的概念,代碼裏面的名字就對應着問題領域或方案領域的這些概念,因此,對於一個命名良好,代碼規範,設計簡潔的系統,要想很是快的理解一個系統,最直接的方式就是RTFC(Read The Fucking Code)。對於一個不斷演進的系統,代碼的可讀性相當重要,首要要解決的問題就是名字,變量名、函數名、類名等都須要仔細斟酌,認真對待,一個可以簡潔,可以清晰表達概念和意圖的名字就顯得尤其重要。程序員

閱讀《代碼整潔之道》這本書後發現其中說的內容在咱們本身項目中比比皆是,隨便拿出一塊代碼均可以當作反面教材給你們講半天。長時間積累,致使代碼發黴變質,取名也是毫無章法,信手拈來。閱讀這樣的代碼,撞南牆的心都有了。下面結合本身項目中的問題和《代碼整潔之道》談談關於命名相關的原則。算法

更多內容:http://game-lab.org/posts/zoc-cleancode-2/函數

1. 原則:名副其實

  • 選名字是件嚴肅的事情,選個好名字很重要。
  • 若是名字須要註釋來補充,那就不是個好名字。
  • 最重要的是要名副其實,名字能表達出概念和意圖。

BAD:post

int t = currentTime.elapse(e); // 消逝的時間,以毫秒計 ... if (t > timeout_value) { Zebra::logger->debug("---一次循環用時 %u 毫秒-----", t); } 

GOOD:編碼

int elapsed_ms = currentTime.elapse(e); ... if (elapsed_ms > timeout_value) { Zebra::logger->debug("-----一次循環用時 %u 毫秒---", elapsed_ms); } 

2. 原則:避免誤導

  • 必須避免留下掩藏代碼本意的錯誤線索
  • 避免使用與本意相悖的詞
  • 提防使用不一樣之處較小的名稱
  • 拼寫先後不一致就是誤導

BAD:spa

std::vector<int> account_list; // _list就是一個誤導, accounts會更好 bool sendToZoneServer(); // 和下面的函數差異很小 bool sendToZoneServers(); // sendToAllZoneServers會好點 

3. 原則:作有意義的區分

  • 代碼是寫給人看的,僅僅是知足編譯器的要求,就會引發混亂
  • 以數字系列命名(a1,a2,...),純屬誤導
  • 無心義的廢話: a, an, the, Info, Data

BAD:debug

void copy(char a1[], char a2[]) { for (size_t i = 0; a1[i] != '\0'; i++) a2[i] = a1[i]; } 

GOOD:設計

void copy(char source[], char dest[]) { for (size_t i = 0; source[i] != '\0'; i++) dest[i] = source[i]; } 

4. 原則:使用可讀的名字

  • 避免過分使用縮寫
  • 可讀的名字交流方便

猜一猜下面的類是幹什麼的?和別人怎麼說這幾個類?代碼規範

根據這些簡直變態的縮寫,若是沒有註釋基本上很難知道是幹什麼的,當你和別人交流的時候,你就不得不一個一個字母來念「X-L-Q-Y」、「L-T-Q Manager」,鬼知道你說的是什麼?PS. XLQY-XianLvQiYuan(仙履奇緣), LTQ-LiaoTianQun(聊天羣),有這樣的名字也是醉了。

BAD:

class XLQY; class FCNV; class LTQManager; 

5. 原則:使用可搜索的名字

  • 避免使用Magic Number
  • 避免使用單字母,或出現頻率極高的短字母組合(注意度的把握)

BAD:

if (obj->base->id == 4661) // 4661是啥玩意? { usetype = Cmd::XXXXXXX; } int e; // 怎麼查找? XXXX:iterator it; // 變量做用的範圍比較大的時候,也不見得是個好名字 

GOOD:

#define OJBECT_FEEDBACK_CARD 4661 if (OJBECT_FEEDBACK_CARD == obj->base->id) { usetype = Cmd::XXXXXXX; } 

6. 原則:避免使用編碼"

  • 匈牙利標記法:
    • Windows API時代留下的玩意
    • 形如:wdXX, dwXXX, strXXX
    • 類型變換致使名存實亡,就有可能出現明明是個DWORD,變量名倒是qwNum

PS.匈牙利命名對於咱們這些在Linux下摸爬滾打的好多年的來講,看着真心彆扭。

  • 成員前綴:
    • 形如:m_name, m_xxx
    • 基本上都無視,爲什麼要屢次一舉

PS.說到這一點,可能有些同窗有不一樣意見了,「我這樣寫是爲了區分紅員變量和臨時變量啊!」,好像這樣寫也沒什麼大不了,遵循代碼規範便可。如Google的C++代碼規範,私有變量形如:xxx_,加後綴_,其目的除了讓你知道這貨是個私有變量,還有一點就是防止有些人圖省事把帶私有變量直接public掉,由於誰也不喜歡在代碼裏面看到大量這些帶把的玩意。

  • 接口和實現:
    • 接口名形如:IXXX, I-接口修飾前綴
    • 類名形如:CXXX, C-類修飾前綴
    • 這些修飾多數時候都是廢話

7. 原則:名字儘可能來自解決方案領域或問題領域

  • 使用解決方案領域名稱:

寫代碼的同窗多數都是都出自CS,術語、算法名、模式名、數學術語儘管用。如AccountVisitor:Visitor模式實現的Account類。

  • 使用問題領域的名稱

咱們代碼裏面多數都是這些名稱,不明白找策劃問問,基本上都是功能相關的名稱。

8. 原則:適當使用有意義的語境

  • 良好命名的類、函數、名稱空間來放置名稱,給讀者提供語境
  • 只有兩三個變量,給名稱前加前綴
  • 事不過三,變量超過三個考慮封裝成概念,添加struct或class

BAD:

// 看着整齊?使用方便? DWORD love_ensure_type_; //當前的愛情保險類型 DWORD love_ensure_ret_; //購買愛情保險迴應標示 DWORD love_ensure_total_; //如今已經蓋章數目 DWORD love_ensure_..._; //... DWORD love_ensure_..._; //... 

最後:咱們的C++命名規範

  • 文件名:

    • 首字母大寫,多個詞組合起來
    • 如: SceneUser.h Sept.h
  • 類名/名稱空間名:

    • 首字母大寫,多個詞組合起來
    • 使用名詞或名詞詞組
    • 避免使用C前綴,如:CSept
    • 如: SceneUser SeptWar
  • 函數名:

    • 首字母小寫
    • 使用動詞或動詞詞組
    • 避免使用孤立的全局函數,能夠封裝在類或名稱空間裏面
    • get, set, is前綴的使用
    • 如: fuckYou(), levelup()
  • 變量名:

    • 所有字母小寫,多個詞如下劃線分隔
    • 私有成員變量加後綴_,公有變量不用
    • 避免使用孤立的全局變量,能夠封裝在類或名稱空間裏面
    • 如: quest_id, questid_

取名是一件嚴肅的事情,咱們須要認真對待,名字表明着一個個概念,名字表明着你想表達的意圖,好名字是可讀代碼的首要條件:

  • 寫下任何一行代碼的時候,內心都要想着本身的代碼是給別人看的。
  • 爲函數、變量、類取個好名字,遵循規範和原則。
  • 見到不符合規範和原則的名字,確絕不留情的幹掉它,特別是功能性的代碼。
相關文章
相關標籤/搜索