如何評價一段代碼

經(jīng)常有人微信問我,什么樣的代碼才算是好代碼茂洒。這個問題其實見仁見智搜变,業(yè)內(nèi)也沒有統(tǒng)一的標(biāo)準(zhǔn)可以使用采缚。我仔細梳理了一下自己評價代碼的方法,總結(jié)了五個評價指標(biāo)挠他。

  • 規(guī)模
  • 執(zhí)行效率
  • 占用空間
  • 可讀性
  • 擴展性

這五個維度相互之間有著或強或弱的關(guān)聯(lián)扳抽,任意兩份代碼之間可以參考這個體系進行大概的比較,但沒有絕對的高下之分殖侵。

1. 規(guī)模

這里的規(guī)模說的是代碼的規(guī)模贸呢,也就是解決同樣問題的程序包含的代碼行數(shù)。如果單從這個因素講拢军,那一定是代碼規(guī)模越小越好楞陷。但規(guī)模越小往往就會讓代碼本身的復(fù)雜程度變高,影響可讀性茉唉。

有個很有趣的情況固蛾,初學(xué)者和技術(shù)大牛兩種水平相差巨大的人都有對代碼規(guī)模的執(zhí)念。不過他們的訴求卻是完全不同的度陆。

1.1 初學(xué)者追求簡單

初學(xué)者評價代碼是不是簡單的最樸素的方法就是看代碼規(guī)模艾凯,他們總是覺得代碼行數(shù)越少的程序就越簡單。經(jīng)常有人在微信中問為什么我給出的解法要寫二十幾行代碼坚芜,而網(wǎng)上的解法卻只有十幾行览芳。于是就讓我講一下那個十幾行的代碼。我只能說鸿竖,那個十幾行的代碼來自《算法導(dǎo)論》沧竟,我需要用4~5個篇幅來講,還不保證能講透徹缚忧。

在編程領(lǐng)域悟泵,往往簡單并不表示易懂,它可能蘊含著更高級更復(fù)雜的思想闪水。這些對于初學(xué)者是有難度的糕非。

for (k = 0; k < n; k++) 
{ 
    for (i = 0; i < n; i++) 
    { 
        for(j = 0; j < n; j++) 
        { 
            if (D[i][j] > D[i][k] + D[k][j]) 
            { 
                D[i][j] = D[i][k] + D[k][j]; 
                P[i][j] = P[i][k]; 
            } 
    } 
}  

這是一個計算臨接矩陣中任意兩點之間距離的一個經(jīng)典算法,叫Floyd球榆,只有六行代碼朽肥。當(dāng)年參加ACM比賽的時候就死記硬背下了這段代碼,后來一直沒有仔細研究過這個算法的原理持钉,目前也只是會用而已衡招。在大部分情況下,它也不是最優(yōu)的算法每强。

1.2 大牛們追求省事

真正的大牛追求代碼行數(shù)少的原因一定是為了提高執(zhí)行效率始腾,但也不乏一些從業(yè)多年沒養(yǎng)成好習(xí)慣也被人稱為“大胖莨簦”的人仗著自己經(jīng)驗豐富圖省事的一些寫法。我就見過這樣的代碼:

typedef struct _tagNode
{
    int m_nID;
    int m_nSN;
    int m_nMode;
    int m_nCode;
}Node;

Node arrNodes[100];

本來應(yīng)該寫這段代碼定義一個數(shù)據(jù)結(jié)構(gòu)浪箭,結(jié)果被某位“大潘胍危”寫成這樣:

int arr[100][4];

九行代碼一下變成了一行,就為了少敲一些奶栖。當(dāng)然匹表,換做初學(xué)者,這樣的二維數(shù)組可能已經(jīng)駕馭不了驼抹。我還見過更夸張的代碼:

int arr[100][50][30][5];

寫這行代碼的人依然是個有多年工作經(jīng)驗的“大派:ⅲ”,這個四維數(shù)組用的風(fēng)生水起框冀。只是坑苦了后來接手他工作的同事。

這樣追求代碼規(guī)模的行為都是不可取的敏簿。

2. 執(zhí)行效率

從某種意義上講明也,如今對程序的第一要求應(yīng)該就是執(zhí)行效率。人們說的最多的就是執(zhí)行效率和運行空間的關(guān)系惯裕,還有執(zhí)行效率和可讀性的關(guān)系温数。

2.1 以空間換時間

隨著硬件設(shè)備的成本越來越低,越來越多的行業(yè)都提倡以空間換時間的設(shè)計思想蜻势。一些能夠通過記錄中間數(shù)據(jù)減少計算量的地方就成了首選的優(yōu)化點撑刺。

最經(jīng)典的利用這個思想的算法就是桶排序:

void main()
{
    int arr[10] = {2, 5, 15, 18, 7, 10, 13, 11, 9, 0};
    int arrSort[20] = { 0 };

    for (int i = 0; i < 10; i++)
    {
        arrSort[arr[i]]++;
    }

    for (int i = 0; i < 20; i++)
    {
        if (arrSort[i] > 0)
        {
            printf("%d ", i);
        }
    }
}

這段代碼通過一個空間為20的一維數(shù)組下標(biāo)進行排序,空間利用是土豪級的握玛。它的特點是排序范圍有多大够傍,就需要一個多大的數(shù)組。

2.2 不能犧牲可讀性

底層程序員喜歡用位運算挠铲,于是常有人把簡單的計算用位運算進行優(yōu)化冕屯,比如把

int a = 10;
int b = a / 2;

改成

int a = 10;
int b = a >>1;

由于位運算的物理特性,下面這段代碼的確效率會更高一些拂苹。不過安聘,很多人看到這種寫法都不一定能反應(yīng)上來。

3. 占用空間

對于一些特殊的行業(yè)瓢棒,比如嵌入式開發(fā)浴韭,編程過程中一定要注意的就是節(jié)省空間。因為嵌入式設(shè)備的RAM普遍比較小脯宿。這時候念颈,桶排序的方法一定是不允許的。另外嗅绰,在申請堆空間時都有嚴格的限制舍肠。

嵌入式開發(fā)中常有類似這樣的代碼:

#define NEED_MAX 800
int* p = new int[NEED_MAX];
if (p == NULL)
{
    return -l;
}

delete[] p;

沒有嵌入式經(jīng)驗的人一定會問搀继,這段代碼申請了一段空間后什么也沒做就釋放掉了,這不是畫蛇添足嗎翠语。其實叽躯,這是一段容錯代碼,就是為了保證系統(tǒng)中有足夠的空間供后面的代碼執(zhí)行肌括。

是不是想想就很可憐点骑,程序運行中突然發(fā)現(xiàn)內(nèi)存不夠了,不得不停掉谍夭。

4. 可讀性

對于越來越提倡代碼規(guī)范的中國軟件行業(yè)來說黑滴,可讀性開始成為不可忽視的重要因素。無論是統(tǒng)一的代碼風(fēng)格紧索,還是規(guī)范的命名袁辈、函數(shù)設(shè)計和注釋,這些都必須注意珠漂。

在某些公司晚缩,代碼規(guī)范被認為是評價代碼的第一要素。鐵打的項目流水的程序員媳危,一段可讀性差的代碼對項目而言很可能意味著滅頂之災(zāi)荞彼。

對于初學(xué)者,代碼規(guī)范這個要素必須非常重視待笑,如果錯過了這個培養(yǎng)良好習(xí)慣的黃金時期鸣皂,后面再改就很難了。

行業(yè)內(nèi)有一些沿襲了很久的陋習(xí)暮蹂,因為追求程序執(zhí)行效率損失可讀性寞缝、為了減少代碼行數(shù)損失可讀性、為了趕工期損失可讀性甚至還有為了省事兒損失可讀性椎侠。在這些思想的驅(qū)使下第租,產(chǎn)生了很多不好的代碼習(xí)慣。

void Swap(int& a, int& b)
{
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
}

這是一個實現(xiàn)變量交換功能的函數(shù)我纪,它利用了^運算的特性慎宾,完成了不借助第三個變量進行交換的動作。有些公司的面試題甚至還會考這個浅悉。但無論從執(zhí)行效率還是從輸入效率來講趟据,它都沒有什么優(yōu)勢。也許唯一的作用就是炫技术健。我建議還是老老實實地這么寫:

void Swap(int& a, int& b)
{
    int t = a;
    a = b;
    b = t;
}

在如今的編譯技術(shù)中汹碱,這段代碼已經(jīng)能夠被優(yōu)化到一個相當(dāng)高的性能了。

再舉個例子:

 g_nScore = student.GetScore() >= p->m_pNext->m_nScore ? student.GetScore() : p->m_pNext->m_nScore;

這句話還是盡量寫成下面這種形式:

if (student.GetScore() >= p->m_pNext->m_nScore)
{
    g_nScore = student.GetScore();
}
else
{
     g_nScore = p->m_pNext->m_nScore;
}

雖然功能上沒有問題荞估,但下面這種寫法更有助于開發(fā)者理清自己的邏輯咳促。

如果你仔細閱讀任意一個公司的代碼規(guī)范文檔稚新,你都會發(fā)現(xiàn)它有一條最重要的指導(dǎo)思想,那就是為了提高代碼可讀性跪腹,允許犧牲一些其他方面的利益褂删。

5. 擴展性

對于一些大型的、生命周期久的項目而言冲茸,擴展性相當(dāng)重要屯阀。但擴展性有一個死敵就是代碼量。仔細研究一下經(jīng)典的23種設(shè)計模式轴术,沒有哪一個不是成倍地提高了代碼量难衰。

在很多資深程序員中,還常常因為是否使用設(shè)計模式引發(fā)爭論逗栽。而這些爭論的焦點就是代碼量和擴展性這對矛盾盖袭。究竟這二者孰輕孰重呢,其實也沒有一定之規(guī)彼宠,完全取決于具體的項目情況苍凛。具體問題具體分析才是王道。

6. 初學(xué)者的權(quán)衡

對于初學(xué)者而言兵志,究竟哪些指標(biāo)應(yīng)該最關(guān)注呢?我認為宣肚,當(dāng)然是可讀性想罕。

初學(xué)者學(xué)習(xí)編程時,最重要的一點就是能夠把樸素的算法用編程語言來實現(xiàn)霉涨。其他的都不重要按价。有時,過早地追求其他四種指標(biāo)會讓你誤入歧途笙瑟。

面對一道題目的多種解法楼镐,你要去做選擇首先該去鉆研哪一個。是那個代碼函數(shù)最少的嗎往枷?是那個運行時間最短的嗎框产?是那個開辟空間最少的嗎?還是那個擴展性最強的错洁。這些都不是秉宿,應(yīng)該是那個可讀性最好的。

可讀性好的代碼一般都不是最短的那一個屯碴,但一定是你最容易學(xué)會的描睦。當(dāng)你掌握了一個正確的解法之后,你的心里就有了底导而,之后再了解其他解法時就更加自信忱叭,學(xué)習(xí)的動力就這樣悄悄地到來了隔崎。

很多新同學(xué)害怕代碼量大的程序,所謂的代碼量大也不過三四十行代碼韵丑,一看到就先緊張爵卒。其實,當(dāng)你靜下心來以子功能為單位一點點地讀下去埂息,你會發(fā)現(xiàn)它不過是幾道課后作業(yè)解法的簡單堆疊技潘,并不難理解。相反千康,很多看似簡單只有十幾行代碼的程序往往是一個大坑享幽,一旦你扎進去,憑自己的本事根本爬不出來拾弃。

可能我說的這些很多初學(xué)者還無法明白值桩,沒關(guān)系先記住,相信在不久的將來你完成了一定數(shù)量的練習(xí)之后豪椿,你就會明白我今天在講些什么奔坟。

我是天花板,讓我們一起在軟件開發(fā)中自我迭代搭盾。
如有任何問題咳秉,歡迎與我聯(lián)系。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鸯隅,一起剝皮案震驚了整個濱河市澜建,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蝌以,老刑警劉巖炕舵,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異跟畅,居然都是意外死亡咽筋,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門徊件,熙熙樓的掌柜王于貴愁眉苦臉地迎上來奸攻,“玉大人,你說我怎么就攤上這事庇忌∥韫浚” “怎么了?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵皆疹,是天一觀的道長疏橄。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么捎迫? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任晃酒,我火速辦了婚禮,結(jié)果婚禮上窄绒,老公的妹妹穿的比我還像新娘贝次。我一直安慰自己,他們只是感情好彰导,可當(dāng)我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布蛔翅。 她就那樣靜靜地躺著,像睡著了一般位谋。 火紅的嫁衣襯著肌膚如雪山析。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天掏父,我揣著相機與錄音笋轨,去河邊找鬼。 笑死赊淑,一個胖子當(dāng)著我的面吹牛爵政,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播陶缺,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼钾挟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了饱岸?” 一聲冷哼從身側(cè)響起等龙,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎伶贰,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體罐栈,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡黍衙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了荠诬。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片琅翻。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖柑贞,靈堂內(nèi)的尸體忽然破棺而出方椎,到底是詐尸還是另有隱情,我是刑警寧澤钧嘶,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布棠众,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏闸拿。R本人自食惡果不足惜空盼,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望新荤。 院中可真熱鬧揽趾,春花似錦、人聲如沸苛骨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽痒芝。三九已至俐筋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吼野,已是汗流浹背校哎。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留瞳步,地道東北人闷哆。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像单起,于是被迫代替她去往敵國和親抱怔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,070評論 25 707
  • 本文把程序員所需掌握的關(guān)鍵知識總結(jié)為三大類19個關(guān)鍵概念嘀倒,然后給出了掌握每個關(guān)鍵概念所需的入門書籍屈留,必讀書籍,以及...
    dle_oxio閱讀 11,097評論 6 244
  • 很多人缺少了另一個人便沒有自己测蘑,無論你最終變成怎樣的人灌危,要相信這些年你都能一個人度過所有。當(dāng)你恐慌害怕時碳胳,最終你會...
    split898閱讀 167評論 0 0
  • 1 有個網(wǎng)友在分答提了一個很典型的問題。 是關(guān)于時間管理的提問诫惭,他的困惑是他想準(zhǔn)備公考翁锡,又想學(xué)英語,還想學(xué)PPT夕土,...
    秋葉大叔閱讀 948評論 0 5
  • 1-1、人為什么活著哈踱? 這是一個每個人都會思考的哲學(xué)問題 在搜索引擎中荒适,每天都有上千人來搜索這個問題的答案,如果再...
    王通專欄閱讀 241評論 0 0