新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 牛人業(yè)話 > 【《代碼整潔之道》精讀與演繹】之二 高質(zhì)量代碼的命名法則

【《代碼整潔之道》精讀與演繹】之二 高質(zhì)量代碼的命名法則

作者: 時(shí)間:2016-08-26 來源:網(wǎng)絡(luò) 收藏

  本文與大家聊一聊中非常關(guān)鍵的一個(gè)點(diǎn),如何更好的對(duì)命名。

本文引用地址:http://butianyuan.cn/article/201608/296112.htm

  一、引言

  《整潔之道》這本書提出了一個(gè)觀點(diǎn):質(zhì)量與其整潔度成正比,干凈的代碼,既在質(zhì)量上可靠,也為后期維護(hù)、升級(jí)奠定了良好基礎(chǔ)。書中介紹的規(guī)則均來自作者多年的實(shí)踐經(jīng)驗(yàn),涵蓋從命名到重構(gòu)的多個(gè)方面,雖為一“家”之言,然誠(chéng)有可資借鑒的價(jià)值。

  但我們知道,很多時(shí)候,理想很豐滿,現(xiàn)實(shí)很骨感,也知道人在江湖,身不由己。因?yàn)轫?xiàng)目的緊迫性,需求的多樣性,我們無法時(shí)時(shí)刻刻都寫出整潔的代碼,保持自己輸出的都是高質(zhì)量、優(yōu)雅的代碼。

  但若我們理解了代碼整潔之道的精髓,我們會(huì)知道怎樣讓自己的代碼更加優(yōu)雅、整潔、易讀、易擴(kuò)展,知道真正整潔的代碼應(yīng)該是怎么樣的,也許就會(huì)漸漸養(yǎng)成持續(xù)輸出整潔代碼的習(xí)慣。

  而且或許你會(huì)發(fā)現(xiàn),若你一直保持輸出整潔代碼的習(xí)慣,長(zhǎng)期來看,會(huì)讓你的整體效率和代碼質(zhì)量大大提升。

  二、本文涉及知識(shí)點(diǎn)思維導(dǎo)圖

  先放出這篇文章所涉及內(nèi)容知識(shí)點(diǎn)的一張思維導(dǎo)圖,就開始正文。大家若是疲于閱讀文章正文,直接看這張圖,也是可以Get到本文的主要知識(shí)點(diǎn)的大概。

  

 

  三、高質(zhì)量代碼的命名法則

  1 名副其實(shí)

  名副其實(shí)說起來貌似很簡(jiǎn)單,但真正做起來,似乎沒那么容易。選個(gè)好名字要花一些時(shí)間,但其實(shí)選好名字之后省下來的時(shí)間,要比之前選名字時(shí)花掉的時(shí)間多得多。

  我們一旦發(fā)現(xiàn)有更好的名稱時(shí),就應(yīng)該換掉之前的舊名稱,這樣做讀你代碼的人(包括你自己),都會(huì)很開心。

  一個(gè)好的變量、函數(shù)或類的名稱應(yīng)該已經(jīng)幾乎答復(fù)了所有的大問題。它應(yīng)該告訴你,這個(gè)名稱所代表的內(nèi)容,為什么會(huì)存在,做了什么事情,應(yīng)該如何用等。

  如果一個(gè)名稱需要注釋來補(bǔ)充才能讓大家明白其真正含義,那其實(shí)就不算是名副其實(shí)。(并不是說不需要注釋,恰如其分的注釋是程序員讓自己代碼錦上添花的好方法,關(guān)于注釋的一些注意事項(xiàng),稍后會(huì)有文章專門涉及。)

  舉個(gè)栗子:

  以下的這句代碼里的d就不算是個(gè)好命名。名稱d什么都沒說,它沒引起我們對(duì)時(shí)間消逝的感覺,更別說單位是天了:

  [cpp] view plain copy print?

  int d; // elapsed time in days||經(jīng)過了幾天時(shí)間

  我們應(yīng)該選擇這樣的指明了計(jì)量對(duì)象和計(jì)量單位的名稱:

  [cpp] view plain copy print?

  int elapsedTimeInDays;

  int daysSinceCreation;

  int daysSinceModification;

  int fileAgeInDays;

  2 避免造成誤導(dǎo)

  我們應(yīng)該避免留下隱藏代碼本意的錯(cuò)誤線索,也應(yīng)該避免使用與本意相悖的詞。例如,別用accountList來指一組賬號(hào),除非它真的是List類型,用accountGroup、bunchOfAccounts,或者直接用accounts,都是更好的選擇。

  盡量提防長(zhǎng)得太像的名稱。想?yún)^(qū)分XYZControllerForEfficientHandlingOfStrings和XYZControllerForEfficientStorageOfStrings,會(huì)花費(fèi)我們太多的時(shí)間。因?yàn)檫@兩個(gè)詞,實(shí)在太相似了。

  以同樣的方式拼寫出同樣的概念才是信息,拼寫前后不一致就是誤導(dǎo)。

  3 盡量做有意義的區(qū)分

  1.盡量避免使用數(shù)字系列命名(a1、a2…….aN)。這樣的名稱純屬誤導(dǎo),因?yàn)楹芏鄷r(shí)候完全沒有提供正確的信息,沒有提供導(dǎo)向作者意圖的線索。

  2.廢話是另一種沒有意義的區(qū)分。如果我們有一個(gè)Product類,還有一個(gè)ProductInfo或ProductData類,那么他們的名稱雖然不同,但意思卻無區(qū)別。這里的Info、Data就像a、an和the一樣,是意義含混的廢話。

  注意,只要體現(xiàn)出有意義的區(qū)分,使用a、the這樣的前綴就沒錯(cuò)。例如,將a用在域內(nèi)變量,把the用于函數(shù)參數(shù)。

  4 盡量使用讀得出來的名稱

  我們要使用讀得出來的名稱。如果名稱讀不出來,討論的時(shí)候就會(huì)不方便且很尷尬,甚至讓旁人覺得很蠢。

  例如,變量名稱是beeceearrthreecee,討論的時(shí)候讀起來簡(jiǎn)直像沒吃藥。

  5 盡量使用可搜索的名稱

  單字母和數(shù)字常量有個(gè)問題,就是很難再一大篇文字中找出來。

  找MAX_CLASSED_PER_STUDENT很容易,但想找數(shù)字7,就很麻煩。

  同樣,字母e也不是個(gè)便于搜索的好變量名。因?yàn)樽鳛橛⑽闹凶畛S玫淖帜福诿總€(gè)程序、每段代碼中都有可能出現(xiàn)。

  名稱長(zhǎng)短應(yīng)與其作用域大小相對(duì)應(yīng),若變量或常量可能在代碼中多處使用,應(yīng)賦予其以便于搜索的名稱。

  舉個(gè)栗子,比較如下兩段代碼:

  [cpp] view plain copy print?

  for (int j=0; j<34; j++)

  {

  s += (t[j]*4)/5;

  }

  和

  [cpp] view plain copy print?

  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;

  }

  按整潔代碼的要求來評(píng)判,第一段代碼會(huì)讓讀者不知所云,第二段代碼比第一段好太多。第二段代碼中,sum并非特別有用的名稱,但至少他搜索得到。采用能表達(dá)意圖的名稱,貌似拉長(zhǎng)了函數(shù)代碼,但要想想看,WORK_DAYS_PER_WEEK要比數(shù)字5好找得多,而列表中也只剩下了體現(xiàn)我們意圖的名稱。

  6 取名不要繞彎子

  我們?nèi)∶臅r(shí)候要避免思維映射,不應(yīng)當(dāng)讓讀者在腦中把你的名稱翻譯為他們熟知的名稱,也就是說取名不要繞彎子,而是要直白,直截了當(dāng)。

  在多數(shù)情況下,單字母不是個(gè)好的命名選擇,除非是在作用域小、沒有名稱沖突的地方,比如循環(huán)。循環(huán)計(jì)數(shù)器自然有可能被命名為i,j或k(最好別用字母l),這是因?yàn)閭鹘y(tǒng)上我們慣用單字母名稱做循環(huán)計(jì)數(shù)器。

  程序員通常都是聰明人,聰明人有時(shí)會(huì)借助腦筋急轉(zhuǎn)彎炫耀其聰明。而聰明程序員和專業(yè)程序員之間的區(qū)別在于,專業(yè)程序員了解,明確就是王道。專業(yè)的程序員善用其能,能編寫出其他人能理解的代碼。

  7 類名盡量用名詞

  類名盡量用名詞或名詞短語,比如Customer, WikiPage,Account, 或 AddressParser。

  類名最好不要是動(dòng)詞。

  8 方法名盡量用動(dòng)詞

  方法名盡量用動(dòng)詞或動(dòng)詞短語。比如postPayment, deletePage, 或者save。

  屬性訪問器、修改器和斷言應(yīng)該根據(jù)其value來命名,并根據(jù)標(biāo)準(zhǔn)加上get、set和is前綴。

  舉個(gè)栗子,這里的getName、setName等命名都很OK:

  [cpp] view plain copy print?

  string name = employee.getName();

  customer.setName("mike");

  if (paycheck.isPosted())...

  而重載構(gòu)造器時(shí),使用描述了參數(shù)的靜態(tài)工廠方法名。如:

  [cpp] view plain copy print?

  Complex fulcrumPoint =Complex.FromRealNumber(666.0);

  通常好于:

  [cpp] view plain copy print?

  Complex fulcrumPoint = new Complex(666.0);

  我們也可以考慮將相應(yīng)的構(gòu)造器設(shè)置為private,強(qiáng)制使用這種命名手段。

  9 每個(gè)概念對(duì)應(yīng)一詞,并一以貫之

  我們需給每個(gè)概念選一個(gè)詞,并且一以貫之。

  例如,使用fetch、retrieve和get來給在多個(gè)類中的同種方法命名,你怎么記得住哪個(gè)類中是哪個(gè)方法呢?

  同樣,在同一堆代碼中混用controller、manager,driver,就會(huì)令人困惑。DeviceManager和Protocol-Controller之間有何根本區(qū)別?為什么不全用controller或者manager?他們都是Driver嗎?這就會(huì)讓讀者以為這兩個(gè)對(duì)象是不同的類型,也分屬不同的類。

  所以,對(duì)于那些會(huì)用到你代碼的程序員,一以貫之的命名法簡(jiǎn)直就是天降福音。

  10 通俗易懂

  我們應(yīng)盡力寫出易于理解的變量名,把代碼寫得讓別人能一目了然,而不必讓人去非常費(fèi)力地去揣摩其含義。我們想要那種大眾化的作者盡責(zé)地寫清楚的通俗易懂的暢銷書風(fēng)格,而不是那種學(xué)者學(xué)院風(fēng)的晦澀論文寫作風(fēng)格。

  11 盡情使用解決方案領(lǐng)域?qū)I(yè)術(shù)語

  記住,只有程序員才會(huì)讀你寫的代碼。所以,盡管去用那些計(jì)算機(jī)科學(xué)(Computer Science,CS)領(lǐng)域的專業(yè)術(shù)語、算法名、模式名、數(shù)學(xué)術(shù)語。

  對(duì)于熟悉訪問者(Visitor)模式的程序來說,名稱AccountVisitor富有意義。給技術(shù)性的事物取個(gè)恰如其分的技術(shù)性名稱,通常就是最靠譜的做法。

  12 添加有意義的語境

  很少有名稱是可以自我說明的。所以,我們需要用有良好命名的類,函數(shù)或名稱空間來放置名稱,給讀者提供語境。若沒能提供放置的地方,還可以給名稱添加前綴。

  舉個(gè)栗子,假如我們有名為firstName、lastName、street、houseNumber、city、state和zipcode的變量。當(dāng)他們擱一塊兒的時(shí)候,的確是構(gòu)成了一個(gè)地址。不過,假如只是在某個(gè)方法中看到一個(gè)孤零零的state呢?我們會(huì)推斷這個(gè)變量是地址的一部分嗎?

  我們可以添加前綴addrFirstName、addrLastName、addrState等,以此提供語境。至少,讀者可以知道這些變量是某個(gè)更大變量的一部分。當(dāng)然,更好的方案是創(chuàng)建名為Address的類。這樣,即便是編譯器也會(huì)知道這些變量是隸屬于某個(gè)更大的概念了。

  另外,只要短名稱足夠好,對(duì)含義的表達(dá)足夠清除,就要比長(zhǎng)名稱更合適。添加有意義的語境甚好,別給名稱添加不必要的語境。

  四、小結(jié)

  其實(shí),取一個(gè)好名字最難的地方在于需要良好的描述技巧和共有的文化背景。與其說這是一種技術(shù)、商業(yè)或管理問題,還不如說這是一種教學(xué)問題。

  不妨試試上面列出的這十二條規(guī)則與要點(diǎn),看看你的代碼可讀性是否有所提升。而如果你是在維護(hù)別人的代碼,或者是在重構(gòu),效果應(yīng)該會(huì)是立竿見影的。

  五、本文涉及知識(shí)點(diǎn)提煉整理

  文章開頭部分已經(jīng)用思維導(dǎo)圖的方式展現(xiàn)了本文的知識(shí)點(diǎn),這邊再貼出一個(gè)文字列表版,方便大家整理:

  要點(diǎn)一:要名副其實(shí)。一個(gè)好的變量、函數(shù)或類的名稱應(yīng)該已經(jīng)答復(fù)了所有的大問題。一個(gè)好名稱可以大概告訴你這個(gè)名稱所代表的內(nèi)容,為什么會(huì)存在,做了什么事情,應(yīng)該如何用等。

  要點(diǎn)二:要避免誤導(dǎo)。我們應(yīng)該避免留下隱藏代碼本意的錯(cuò)誤線索,也應(yīng)該避免使用與本意相悖的詞。

  要點(diǎn)三:盡量做有意義的區(qū)分。盡量避免使用數(shù)字系列命名(a1、a2…….aN)和沒有意義的區(qū)分。

  要點(diǎn)四:盡量使用讀得出來的名稱。如名稱讀不出來,討論的時(shí)候會(huì)不方便且很尷尬。

  要點(diǎn)五:盡量使用可搜索的名稱。名稱長(zhǎng)短應(yīng)與其作用域大小相對(duì)應(yīng),若變量或常量可能在代碼中多處使用,應(yīng)賦予其以便于搜索的名稱。

  要點(diǎn)六:取名不要繞彎子。取名要直白,要直截了當(dāng),明確就是王道。

  要點(diǎn)七:類名盡量用名詞。類名盡量用名詞或名詞短語,最好不要是動(dòng)詞。

  要點(diǎn)八:方法名盡量用動(dòng)詞。方法名盡量用動(dòng)詞或動(dòng)詞短語。

  要點(diǎn)九:每個(gè)概念對(duì)應(yīng)一詞,并一以貫之。對(duì)于那些會(huì)用到你代碼的程序員,一以貫之的命名法簡(jiǎn)直就是天降福音。

  要點(diǎn)十:通俗易懂。應(yīng)盡力寫出易于理解的變量名,要把代碼寫得讓別人能一目了然,而不必讓人去非常費(fèi)力地去揣摩其含義。

  要點(diǎn)十一:盡情使用解決方案領(lǐng)域?qū)I(yè)術(shù)語。盡管去用那些計(jì)算機(jī)科學(xué)領(lǐng)域的專業(yè)術(shù)語、算法名、模式名、數(shù)學(xué)術(shù)語。

  要點(diǎn)十二:要添加有意義的語境。需要用有良好命名的類,函數(shù)或名稱空間來放置名稱,給讀者提供語境。若沒能提供放置的地方,還可以給名稱添加前綴。



關(guān)鍵詞: 編程 代碼

評(píng)論


技術(shù)專區(qū)

關(guān)閉