如何編寫可讀的代碼
代碼最重要的讀者不再是編譯器、解釋器或者電腦,而是人。寫出的代碼能讓人易于理解、輕松維護(hù)、容易擴(kuò)展的程序員才是專業(yè)的程序員。
代碼應(yīng)當(dāng)易于理解
在過去的五年里,我們收集了上百個“壞代碼”的例子(其中很大一部分是我們自己寫的),并且分析是什么原因使它們變壞,使用什么樣的原則和技術(shù)可以讓它們變好。我們發(fā)現(xiàn)所有的原則都源自同一個主題思想。
關(guān)鍵思想:代碼應(yīng)當(dāng)易于理解
我們相信這是當(dāng)你考慮要如何寫代碼時可以使用的最重要的指導(dǎo)原則。我們會展示如何把這條原則應(yīng)用于你每天編碼工作的各個不同方面。但在開始之前,我們會詳細(xì)地介紹這條原則并證明它為什么這么重要。
是什么讓代碼變得“更好”
大多數(shù)程序員(包括兩位作者)依靠直覺和靈感來決定如何編程。我們都知道這樣的代碼:
- for (Node* node = list->head; node != NULL; nodenode = node->next)
- Print (node->data);
比下面的代碼好:
- Node* node = list->head;
- if (node == NULL) return;
- while (node->next != NULL) {
- Print (node->data);
- node = node->next;
- }
- if (node != NULL) Print (node->data);
(盡管兩個例子的行為完全相同。)但很多時候這個選擇會更艱難。例如,這段代碼:
- return exponent >= 0 ? mantissa * (1 << exponent) : mantissa / (1 << -exponent);
它比下面這段要好些還是差些?
- if (exponent >= 0) {
- return mantissa * (1 << exponent);
- } else {
- return mantissa / (1 << -exponent);
- }
第一個版本更緊湊,但第二個版本更直白。哪個標(biāo)準(zhǔn)更重要呢?一般情況下,在寫代碼時你如何來選擇?
可讀性基本定理
在對很多這樣的例子進(jìn)行研究后,我們總結(jié)出,有一種對可讀性的度量比其他任何的度量都要重要。因?yàn)樗侨绱酥匾?,我們把它叫?ldquo;可讀性基本定理”。
關(guān)鍵思想:代碼的寫法應(yīng)當(dāng)使別人理解它所需的時間最小化。
這是什么意思?其實(shí)很直接,如果你叫一個普通的同事過來,測算一下他通讀你的代碼并理解它所需的時間,這個“理解代碼時間”就是你要最小化的理論度量。
并且當(dāng)我們說“理解”時,我們對這個詞有個很高的標(biāo)準(zhǔn)。如果有人真的完全理解了你的代碼,他就應(yīng)該能改動它、找出缺陷并且明白它是如何與你代碼的其他部分交互的。
現(xiàn)在,你可能會想:“誰會關(guān)心是不是有人能理解它?我是唯一使用這段代碼的人!”就算你從事只有一個人的項(xiàng)目,這個目標(biāo)也是值得的。那個“其他人”可能就是 6 個月的你自己,那時你自己的代碼看上去已經(jīng)很陌生了。而且你永遠(yuǎn)也不會知道——說不定別人會加入你的項(xiàng)目,或者你“丟棄的代碼”會在其他項(xiàng)目里重用。
總是越小越好嗎
一般來講,你解決問題所用的代碼越少就越好。很可能理解 2000 行代碼寫成的類所需的時間比 5000 行的類要短。但少的代碼并不總是更好!很多時候,像下面這樣的一行表達(dá)式:
- assert ((!(bucket = FindBucket (key))) !bucket->IsOccupied ());
理解起來要比兩行代碼花更多時間:
- bucket = FindBucket (key);
- if (bucket != NULL) assert (!bucket->IsOccupied ());
類似地,一條注釋可以讓你更快地理解代碼,盡管它給代碼增加了長度:
- // Fast version of “hash = (65599 * hash) + c”
- hash = (hash << 6) + (hash << 16) – hash + c;
因此盡管減少代碼行數(shù)是一個好目標(biāo),但把理解代碼所需的時間最小化是一個更好的目標(biāo)。
理解代碼所需的時間是否與其他目標(biāo)有沖突
你可能在想:“那么其他約束呢?像是使代碼更有效率,或者有好的架構(gòu),或者容易測試等?這些不會在有些時候與使代碼容易理解這個目標(biāo)沖突嗎?”我們發(fā)現(xiàn)這些其他目標(biāo)根本就不會互相影響。就算是在需要高度優(yōu)化代碼的領(lǐng)域,還是有辦法能讓代碼同時可讀性更高。并且讓你的代碼容易理解往往會把它引向好的架構(gòu)且容易測試。有些程序員對于任何沒有完美地分解的代碼都不自覺地想要修正它。這時很重要的是要停下來并且想一下:“這段代碼容易理解嗎?”如果容易,可能轉(zhuǎn)而關(guān)注其他代碼是沒有問題的。
最難的部分
是的,要經(jīng)常地想一想其他人是不是會覺得你的代碼容易理解,這需要額外的時間。這樣做就需要你打開大腦中從前在編碼時可能沒有打開的那部分功能。但如果你接受了這個目標(biāo)(像我們一樣),我們可以肯定你會成為一個更好的程序員,會產(chǎn)生更少的缺陷,從工作中獲得更多的自豪,并且編寫出你周圍人都愛用的代碼。
本文節(jié)選自《編寫可讀代碼的藝術(shù)》一書,Dustin Boswell、Trevor Foucher 著,尹哲、鄭秀雯譯,由機(jī)械工業(yè)出版社出版。
原文鏈接:http://blog.jobbole.com/23599/
【編輯推薦】