![]()
過去三十年,硅谷有個(gè)政治正確:誰提"代碼行數(shù)"誰外行。
Stack Overflow上點(diǎn)贊最高的回答告訴你這是"最無意義的指標(biāo)"。CTO們?cè)贏ll Hands大會(huì)上把它當(dāng)笑話講。連《人月神話》的讀者都學(xué)會(huì)了用"本質(zhì)復(fù)雜度"這個(gè)詞來顯得專業(yè)。
但MIT和NASA聯(lián)合做的一項(xiàng)研究,讓這套話語體系有點(diǎn)站不住腳了。
被污名化的度量衡
先還原一下"代碼行數(shù)無用論"是怎么成為共識(shí)的。
1990年代,IBM的Capers Jones開始統(tǒng)計(jì)軟件項(xiàng)目數(shù)據(jù),發(fā)現(xiàn)不同語言、不同風(fēng)格的程序員產(chǎn)出差異極大。有人一天寫500行,有人重構(gòu)完反而刪了200行。管理層試圖用行數(shù)考核,結(jié)果催生出一行代碼拆成三行的"分行藝術(shù)"。
這個(gè)故事在程序員社區(qū)口耳相傳,逐漸變成一種身份認(rèn)同:懂行的人都不看行數(shù)。
但這里有個(gè)偷換概念。把"行數(shù)作為KPI很蠢"推廣成"行數(shù)作為度量衡無效",相當(dāng)于因?yàn)橛腥擞皿w重歧視胖子,就宣布體重秤是偽科學(xué)。
Fred Brooks在1986年區(qū)分過"本質(zhì)復(fù)雜度"和"偶然復(fù)雜度"。前者是問題本身決定的,比如火星著陸的物理約束;后者是人為增加的,比如選錯(cuò)了框架、寫了冗余的抽象層。
批評(píng)者常用這個(gè)區(qū)分來攻擊行數(shù):你量的是總復(fù)雜度,但我們應(yīng)該只關(guān)心本質(zhì)復(fù)雜度。
問題是,本質(zhì)復(fù)雜度無法直接觀測(cè)。你能精確測(cè)量"火星著陸的難度"嗎?不能。你能做的是:比較兩個(gè)都成功著陸火星的軟件,看哪個(gè)更簡潔。
這時(shí)候行數(shù)就成了最誠實(shí)的參照系。
MIT的研究說了什么
MIT計(jì)算機(jī)科學(xué)與人工智能實(shí)驗(yàn)室(CSAIL)和NASA的聯(lián)合團(tuán)隊(duì),系統(tǒng)測(cè)試了市面上所有主流的代碼復(fù)雜度度量方法。
結(jié)果讓研究者自己都意外。
他們對(duì)比了圈復(fù)雜度(Cyclomatic Complexity)、Halstead度量、可維護(hù)性指數(shù)等十幾種"科學(xué)"指標(biāo)。這些指標(biāo)的計(jì)算公式動(dòng)輒涉及對(duì)數(shù)運(yùn)算、權(quán)重系數(shù),看起來比簡單數(shù)行數(shù)專業(yè)得多。
但預(yù)測(cè)軟件缺陷率、維護(hù)成本、理解難度時(shí),它們的準(zhǔn)確度要么和行數(shù)持平,要么更差。
Victor Basili和David Hutchens在論文里寫得很直接:「由于行數(shù)極易計(jì)算,且大量研究者發(fā)現(xiàn)它能可靠地度量復(fù)雜度,它必須被視為這類研究中的基準(zhǔn)指標(biāo)。我們未能找到任何顯著優(yōu)于行數(shù)的指標(biāo)。」
換句話說,那些復(fù)雜的公式,很多只是"給行數(shù)穿了件風(fēng)衣"——換個(gè)形式包裝同樣的信息,還損失了透明度。
這個(gè)發(fā)現(xiàn)不是孤例。2015年,微軟研究院分析了Windows操作系統(tǒng)的開發(fā)數(shù)據(jù),發(fā)現(xiàn)文件行數(shù)與缺陷密度的相關(guān)性,比任何靜態(tài)分析工具都穩(wěn)定。2021年,GitHub的Copilot團(tuán)隊(duì)用行數(shù)作為訓(xùn)練數(shù)據(jù)質(zhì)量的篩選標(biāo)準(zhǔn),因?yàn)?它意外地有效"。
為什么行數(shù)有效
![]()
行數(shù)能預(yù)測(cè)復(fù)雜度,背后有個(gè)簡單的統(tǒng)計(jì)直覺:軟件是信息的載體,而信息需要空間。
一個(gè)處理100種邊緣情況的模塊,幾乎不可能比處理10種的更短——除非你在用極度壓縮的寫法,但那本身就會(huì)引入新的復(fù)雜度(可讀性損失)。
這不是說行數(shù)等于質(zhì)量。兩個(gè)同樣長度的程序,一個(gè)可能結(jié)構(gòu)清晰,一個(gè)可能是意大利面條代碼。但長度給了你一個(gè)錨點(diǎn):在比較同類系統(tǒng)時(shí),顯著更長的那個(gè),大概率承載了更多需要理解的東西。
NASA的Jet Propulsion Laboratory有個(gè)內(nèi)部實(shí)踐:關(guān)鍵任務(wù)軟件的模塊,行數(shù)超過閾值必須強(qiáng)制評(píng)審。他們不考核"寫了多少行",但用行數(shù)來標(biāo)記風(fēng)險(xiǎn)點(diǎn)。這個(gè)做法從火星探路者時(shí)代延續(xù)至今。
諷刺的是,JPL的工程師們同時(shí)在公開演講里批評(píng)"行數(shù)是愚蠢指標(biāo)"——直到2020年,一位研究員把內(nèi)部手冊(cè)泄露出來,社區(qū)才發(fā)現(xiàn)這套"政治正確"和實(shí)際操作的分裂。
被誤解的"簡潔"
反對(duì)行數(shù)的人,最喜歡舉的例子是"重構(gòu)后代碼變短了,所以變好了"。
這混淆了兩個(gè)維度。重構(gòu)確實(shí)經(jīng)常減少行數(shù),但減少的是"偶然復(fù)雜度"——那些因?yàn)樵O(shè)計(jì)不良而多余的部分。本質(zhì)復(fù)雜度沒變,只是表達(dá)得更緊湊了。
用Brooks的話說:「軟件工程師必須掌握的大部分復(fù)雜度,是任意強(qiáng)加的復(fù)雜度,由他的接口必須遵從的眾多系統(tǒng)所強(qiáng)制……這無法通過任何單獨(dú)的重設(shè)計(jì)來消除。」
當(dāng)你看到兩個(gè)實(shí)現(xiàn)相同功能的程序,一個(gè)500行,一個(gè)2000行,行數(shù)告訴你的是:后者可能需要你理解四倍的信息量,才能定位一個(gè)bug或添加功能。
這不意味著2000行的那個(gè)"更差"。它可能處理了更多真實(shí)世界的混亂——時(shí)區(qū)、網(wǎng)絡(luò)中斷、用戶輸入的emoji。但行數(shù)誠實(shí)地標(biāo)記了這種成本。
問題從來不是行數(shù)本身,而是人們?cè)趺从盟?/p>
行數(shù)在測(cè)量什么
澄清一個(gè)常見誤解:行數(shù)測(cè)量的是"復(fù)雜度",不是"工作量"或"價(jià)值"。
一個(gè)程序員花一周刪掉1000行遺留代碼,創(chuàng)造的價(jià)值可能遠(yuǎn)超另一個(gè)花一周添加500行新功能的人。但刪掉代碼的那個(gè)模塊,復(fù)雜度確實(shí)下降了——這是好事,也是行數(shù)能反映的。
同樣,一個(gè)算法從O(n2)優(yōu)化到O(n log n),代碼可能變長(因?yàn)橐幚砀噙吔缜闆r),但運(yùn)行時(shí)的計(jì)算復(fù)雜度下降了。這時(shí)候行數(shù)上升,不代表"更差",只是代表"不同的權(quán)衡"。
行數(shù)像體重秤:它告訴你質(zhì)量,不告訴你肌肉脂肪比,不告訴你健康狀態(tài),不告訴你該不該減肥。但否認(rèn)質(zhì)量可以測(cè)量,是放棄了一個(gè)有用的參考系。
軟件工程研究者Chris Bird在微軟時(shí)的發(fā)現(xiàn)很有代表性:團(tuán)隊(duì)規(guī)模與代碼行數(shù)的增長曲線,比任何"敏捷成熟度評(píng)估"都更能預(yù)測(cè)項(xiàng)目延期風(fēng)險(xiǎn)。這不是因?yàn)樾袛?shù)導(dǎo)致延期,而是因?yàn)樾袛?shù)誠實(shí)反映了系統(tǒng)規(guī)模,而規(guī)模是復(fù)雜度的代理變量。
為什么這個(gè)行業(yè)恨行數(shù)
既然行數(shù)有用,為什么被污名化得這么徹底?
一部分是歷史包袱。1980-90年代的管理層確實(shí)濫用行數(shù),把它和獎(jiǎng)金掛鉤,催生了大量垃圾代碼。程序員的反彈是正當(dāng)?shù)模^度校正了。
![]()
另一部分是專業(yè)身份的建構(gòu)。"我們不用這種粗糙的指標(biāo)"是一種區(qū)隔策略,把"真正的工程師"和"不懂技術(shù)的外行"分開。這在社交媒體時(shí)代被放大——批評(píng)行數(shù)是安全的點(diǎn)贊收割機(jī)。
還有一個(gè)更隱蔽的因素:行數(shù)太透明了。任何人都能數(shù),不需要買SonarQube的許可證,不需要考認(rèn)證。這讓依賴復(fù)雜度度量工具吃飯的人,有動(dòng)力貶低這個(gè)"平民替代方案"。
但最深層的原因可能是心理。程序員愿意相信,自己的工作是創(chuàng)造性勞動(dòng),不可被簡單度量。承認(rèn)行數(shù)有意義,有點(diǎn)像作家承認(rèn)字?jǐn)?shù)和小說復(fù)雜度相關(guān)——技術(shù)上正確,但感覺上降格了。
問題是,感覺不等于事實(shí)。
行數(shù)的正確打開方式
那該怎么用行數(shù)?幾個(gè)從NASA和大型開源項(xiàng)目提煉的實(shí)踐:
橫向比較時(shí)作為基準(zhǔn)。兩個(gè)團(tuán)隊(duì)實(shí)現(xiàn)類似功能,行數(shù)差異過大值得追問——是技術(shù)選型不同,還是一方積累了更多技術(shù)債?
縱向追蹤時(shí)看趨勢(shì)。單個(gè)模塊的行數(shù)增長曲線,比絕對(duì)值更有信息量。突然飆升往往對(duì)應(yīng)設(shè)計(jì)腐化或需求蔓延。
結(jié)合變更頻率。靜態(tài)行數(shù)+動(dòng)態(tài)修改次數(shù),能識(shí)別"復(fù)雜且活躍"的高風(fēng)險(xiǎn)區(qū)域。Linux內(nèi)核的維護(hù)者用這個(gè)組合來分配review資源。
設(shè)定閾值而非目標(biāo)。JPL的編碼規(guī)范規(guī)定,單個(gè)函數(shù)超過75行必須書面說明理由。這不是考核,是強(qiáng)制暫停和反思的機(jī)制。
關(guān)鍵區(qū)別:行數(shù)是診斷工具,不是績效指標(biāo)。當(dāng)你用它理解系統(tǒng),它有效;當(dāng)你用它驅(qū)動(dòng)行為,它扭曲。
這和醫(yī)學(xué)影像類似。CT掃描是強(qiáng)大的診斷工具,但如果你想用它考核"誰發(fā)現(xiàn)的腫瘤最多",醫(yī)生就會(huì)開始過度檢查。
復(fù)雜度不可避免
回到Brooks的核心洞察:軟件復(fù)雜度有兩類,本質(zhì)的和偶然的。我們討厭的是后者,但經(jīng)常假裝前者也不存在。
一個(gè)火星著陸器需要理解大氣動(dòng)力學(xué)、推進(jìn)器控制、地形識(shí)別。這些復(fù)雜度不會(huì)因?yàn)槟銚Q編程語言、用敏捷方法、或者"賦能團(tuán)隊(duì)"就消失。它們只是被編碼進(jìn)了軟件,而編碼需要行數(shù)。
聲稱"行數(shù)無意義",有時(shí)是逃避這個(gè)現(xiàn)實(shí)的方式。如果復(fù)雜度無法測(cè)量,那也無法被管理,無法被問責(zé)。
但MIT的研究和NASA的實(shí)踐表明,復(fù)雜度可以被近似測(cè)量,而行數(shù)是目前最好的近似。它不是完美的,只是"比所有試圖取代它的東西更好"。
軟件工程師Basili和Hutchens的論文結(jié)尾有個(gè)微妙的謙遜:「我們未能找到顯著優(yōu)于行數(shù)的指標(biāo)」——說的是"迄今為止"。他們留了個(gè)口子,承認(rèn)未來可能有更好的方法。
但三十多年過去了,這個(gè)口子還在。圈復(fù)雜度、認(rèn)知復(fù)雜度、各種AI驅(qū)動(dòng)的"代碼健康度"評(píng)分輪番登場(chǎng),又輪番被證偽。
行數(shù)依然站在原地,穿著它的風(fēng)衣。
下次聽到有人說"代碼行數(shù)是最糟糕的指標(biāo)",你可以問一句:那什么更好?對(duì)方大概率會(huì)提到某個(gè)你查過論文后發(fā)現(xiàn)相關(guān)性更差的替代方案。
這不是為行數(shù)辯護(hù),是為誠實(shí)度量辯護(hù)——哪怕度量結(jié)果不符合我們想要講述的故事。
如果行數(shù)真的無效,為什么Linux內(nèi)核的維護(hù)者還在用它篩選需要重點(diǎn)review的補(bǔ)丁?為什么SpaceX的飛行軟件規(guī)范里明確寫著模塊行數(shù)上限?為什么GitHub的AI代碼助手用行數(shù)來評(píng)估訓(xùn)練數(shù)據(jù)質(zhì)量?
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.