為什么你寫的代碼別人看不懂?
策劃 | 劉燕
作者 | Rhea Moutafis Following
翻譯 | 劉雅夢(mèng)
編輯 | Linda
好的事物都是在結(jié)構(gòu)和混亂的健康平衡中產(chǎn)生的。
為什么你的代碼這么潦草?
為什么每個(gè)開發(fā)人員都認(rèn)為自己編寫的代碼是完全可以理解的?為什么同一個(gè)開發(fā)人員不能看懂和理解別人編寫的代碼,從而很少能對(duì)其進(jìn)行維護(hù)呢?
是因?yàn)樗麄儗懙拇a都很潦草。也就是說,代碼現(xiàn)在可以正常運(yùn)行,但由于它相當(dāng)混亂,不具備很好的可擴(kuò)展性或通用性。計(jì)算機(jī)科學(xué)家是個(gè)例外 — 他們編寫的代碼很“漂亮”,但不起作用。
原因 1:對(duì)于計(jì)算機(jī)科學(xué)家來說,編碼是一門藝術(shù)。對(duì)其他人來說,它僅是個(gè)工具
計(jì)算機(jī)科學(xué)家編碼是因?yàn)樗麄兿刖幋a。其他人編碼是因?yàn)樗麄兿胪瓿晒ぷ鳌?/p>
一個(gè)普通的開發(fā)人員會(huì)根據(jù)他們能想到的第一個(gè)想法來構(gòu)建程序。然后他們會(huì)在這個(gè)想法的基礎(chǔ)上繼續(xù)延伸,直到構(gòu)建出類似 MVP 的東西。通常情況下,他們甚至不會(huì)考慮是否還有其他可行的方法。
相反,計(jì)算機(jī)科學(xué)家會(huì)考慮實(shí)現(xiàn)的各種方案,權(quán)衡每種方案的利弊。幾周之后,他們可能還只是編寫了一段漂亮但仍然不能完全運(yùn)行的代碼,因?yàn)橛?jì)算機(jī)科學(xué)家還沒有決定好輸出要采用什么格式。
很多潦草代碼的產(chǎn)生是由于開發(fā)人員僅從一個(gè)簡(jiǎn)單的工具開始,然后就有機(jī)地增長(zhǎng)代碼造成的。相比之下,計(jì)算機(jī)科學(xué)家通常會(huì)先構(gòu)建一個(gè)結(jié)構(gòu)框架,然后再在框架內(nèi)實(shí)現(xiàn)編碼。
有些代碼看起來很整潔,但實(shí)際上卻很混亂。
為了避免 Coder Block 能按時(shí)交付,采用有機(jī)的方法是最好的。但是,如果我們想要編寫可持續(xù)的代碼,可能就需要將結(jié)構(gòu)框架放在第一位了。
原因 2:開發(fā)人員并不總是以讀者為中心來編碼
即使是在協(xié)作項(xiàng)目中,開發(fā)人員也傾向于在編碼時(shí)僅考慮其功能。他們這樣做時(shí),就會(huì)忘記“代碼也是需要維護(hù)”的這一事實(shí)。
問題在于這種心態(tài)會(huì)適得其反。當(dāng)開發(fā)人員想在三個(gè)月后再添加一個(gè)特性時(shí),他們可能連自己都無法理解自己編寫的代碼了。這種情況比你想象中的要更常見!
當(dāng)另一個(gè)開發(fā)人員被要求實(shí)現(xiàn)這個(gè)新特性時(shí),情況會(huì)變得更加復(fù)雜。由于項(xiàng)目規(guī)模大小的不同,理解其他人編寫的代碼可能需要花費(fèi)幾天到幾周的時(shí)間。
原因 3:風(fēng)格很重要
每個(gè)人都以不同的方式編碼。有人討厭行注釋,有人則喜歡。有人會(huì)在第一行的上面注釋它們的功能,有人則會(huì)在第一行的下面注釋。有人喜歡使用 switch 開關(guān)語(yǔ)句,有人則討厭。
這就是為什么一段代碼對(duì)一個(gè)人來說可能很可怕,但對(duì)另一個(gè)人來說卻很好。
當(dāng)你獨(dú)自工作時(shí),這沒什么問題。但如今,很多軟件都是協(xié)同構(gòu)建的。因此,在項(xiàng)目的早期,制定風(fēng)格指南是很重要的。
當(dāng)然,我們還需要確保所有的開發(fā)人員都遵守它。否則,我們將以代碼更加混亂而告終,因?yàn)榇藭r(shí)代碼會(huì)是各種不同約定混雜后的產(chǎn)物。
及時(shí)修復(fù)是有益的,但從長(zhǎng)遠(yuǎn)來看可能會(huì)導(dǎo)致大混亂。
理由原因 4:即時(shí)獎(jiǎng)勵(lì)的謬論
你被一個(gè)問題困擾了很幾天,當(dāng)你終于找到了解決方案時(shí),你是否會(huì)感到興奮?這是一個(gè)非常激動(dòng)人心的時(shí)刻。
問題在于,當(dāng)開發(fā)人員追求快速修復(fù)時(shí),往往會(huì)忽略長(zhǎng)期的問題。例如,他們可能修復(fù)了一個(gè) bug 或者添加了一個(gè)特性,但是他們沒有意識(shí)到代碼結(jié)構(gòu)已經(jīng)過時(shí)了。
這意味著每當(dāng)他們要添加一個(gè)新特性時(shí),都不得不投入更多的工作。相反,從長(zhǎng)遠(yuǎn)來看,對(duì)程序進(jìn)行一次重構(gòu),當(dāng)添加更多新特性時(shí),將會(huì)變得更加容易。
如果你更喜歡快速修復(fù)而不是解決潛在的問題,沒關(guān)系,這樣的人很多。人類的獎(jiǎng)勵(lì)系統(tǒng)更容易受到短期修正而不是長(zhǎng)期變化的影響。但這樣一來,我們就欠下了“技術(shù)債”。從長(zhǎng)遠(yuǎn)來看,這會(huì)讓我們付出更多代價(jià)。
整潔 vs 混亂的危險(xiǎn)
聲稱自己總是編寫整潔代碼的開發(fā)人員要么是撒謊,要么是高估了自己。也就是說,我們不想編寫太整潔的代碼是有原因的:
- 如果你的目標(biāo)是從頭開始編寫整潔的代碼,那么你就增加了 Coder Block 的風(fēng)險(xiǎn)。為了避免主要的 Block 發(fā)生,最好是在一開始時(shí)就有機(jī)地增加代碼。這尤其適用于初學(xué)者。
- 一些開發(fā)人員會(huì)花一整天的時(shí)間來清理他們的代碼,只是為了美觀,而沒有其他原因。當(dāng)然,如果還有很多其他協(xié)作者,或者代碼可以以任何一種方式來呈現(xiàn),這都是無可厚非的。但通常情況下,潤(rùn)色代碼的效果就像一般的醫(yī)療整形手術(shù)一樣——可能看起來很不錯(cuò),但并不解決任何更深層次的問題。
另一方面,我們也不希望代碼太混亂。太混亂會(huì)使我們的代碼無法維護(hù)。缺乏維護(hù)會(huì)導(dǎo)致代碼“腐爛”,從長(zhǎng)遠(yuǎn)來看,項(xiàng)目將會(huì)被丟棄,因?yàn)樗鼈兊谋状笥诶?/p>
因此,我們需要的是在快速拿結(jié)果和代碼可維護(hù)性之間維持健康的平衡。大多數(shù)開發(fā)人員都會(huì)陷入代碼混亂的困境,所以提高整潔度才是解決之道。好消息是,一些好的習(xí)慣可以對(duì)開發(fā)人員的代碼整潔度和生產(chǎn)力產(chǎn)生巨大的影響。
技巧 1:盡早進(jìn)行測(cè)試并提高測(cè)試頻度
一些開發(fā)人員對(duì)他們的技術(shù)非常有信心,以至于他們?cè)诓贿\(yùn)行任何測(cè)試的情況下就構(gòu)建完了整個(gè)項(xiàng)目。但是,除非手頭的任務(wù)是完全無關(guān)緊要,否則只會(huì)適得其反。
當(dāng)他們嘗試編譯或執(zhí)行程序時(shí),屏幕上就會(huì)充滿各種錯(cuò)誤消息。或者,更糟糕的是,直到幾個(gè)月后,當(dāng)用戶意識(shí)到程序沒有按照預(yù)期運(yùn)行時(shí),錯(cuò)誤才會(huì)被發(fā)現(xiàn)。
這些都是不好的做法。如果在技術(shù)部門工作可以教會(huì)我們什么的話,那應(yīng)該是:
如果你沒有對(duì)所有場(chǎng)景進(jìn)行測(cè)試,就永遠(yuǎn)不要假設(shè)某些東西能像預(yù)期的那樣運(yùn)行。
盡可能快速地構(gòu)建一些可執(zhí)行的代碼。即使它非常非常的簡(jiǎn)單。一有機(jī)會(huì)就測(cè)試一下它。這樣你就可以在錯(cuò)誤構(gòu)建完之后能立即修復(fù)它們了。
技巧 2:結(jié)構(gòu)良好但格式混亂
只要代碼的底層結(jié)構(gòu)是好的,追求快速修復(fù)也是可以的。但實(shí)際情況是,開發(fā)人員試圖在混亂或過時(shí)的代碼結(jié)構(gòu)中實(shí)現(xiàn)快速修復(fù)。
在這種情況下,最好花時(shí)間重構(gòu)代碼。如果需要修復(fù)的代碼沒有正確的注釋,或者變量命名詞不達(dá)意,那也不是沒得救。但是,試圖在充滿 bug 的代碼中構(gòu)建一個(gè)干凈的特性卻是浪費(fèi)時(shí)間和資源的,不管怎么樣,我們可能需要重寫很多其他特性。
因此,在代碼整潔度和速度之間進(jìn)行選擇的一個(gè)很好的折衷方案是保持底層結(jié)構(gòu)的整潔和更新,但在細(xì)節(jié)上可以容忍混亂。
技巧 3:為重構(gòu)分配時(shí)間
每次你搞得一團(tuán)糟,你都是在制造技術(shù)債。就像貨幣債一樣,你借貸的時(shí)間越長(zhǎng),它的成本就越高。
另一方面,花上幾天甚至幾周的時(shí)間來清理代碼,對(duì)一般的開發(fā)人員來說,并不能受到鼓舞。這就是為什么建立一個(gè)每天都能還一點(diǎn)債務(wù)的習(xí)慣是非常有用的。
一個(gè)好的開始方法是每天花費(fèi) 15% 的時(shí)間來進(jìn)行重構(gòu)。我稱之為時(shí)間規(guī)則。你會(huì)為你能改進(jìn)的代碼量感到驚訝的!
技巧 4:留下比你發(fā)現(xiàn)時(shí)更整潔的代碼
我把這叫做“廁所規(guī)則”。如果每個(gè)人在離開公廁時(shí),公廁至少要和他們進(jìn)入時(shí)一樣干凈,那么他們將會(huì)處于無可挑剔的狀態(tài)。
從大多數(shù)公共廁所的狀況來看,現(xiàn)實(shí)并非如此。維持這樣的規(guī)則需要每個(gè)開發(fā)人員都遵守紀(jì)律,而這反過來還需要一個(gè)優(yōu)秀的管理者。
但遵守這種紀(jì)律是值得的,因?yàn)殡S著時(shí)間的推移,回報(bào)是巨大的。我們不可能通過做不可能的事情來實(shí)現(xiàn)不可能。我們只需通過做一些好的決定就能實(shí)現(xiàn)它,并且每天都朝著這個(gè)目標(biāo)邁出一小步即可。
技巧 5:請(qǐng)求審查!
有時(shí),代碼會(huì)很混亂,是因?yàn)殚_發(fā)人員不知道如何才能做得更好。例如,代碼可能在使用 map 更簡(jiǎn)單的情況下使用了 switch 語(yǔ)句。在這種情況下,來自高級(jí)開發(fā)人員的建議就是關(guān)鍵。
建立代碼審查的例程可以幫助我們創(chuàng)建一個(gè)反饋機(jī)制。這將會(huì)改善年輕開發(fā)人員的學(xué)習(xí)曲線,并能培養(yǎng)一種健康討論的文化。
就像“廁所規(guī)則”和時(shí)間規(guī)則一樣,例程是關(guān)鍵。請(qǐng)求審查應(yīng)該是初級(jí)開發(fā)人員的一種習(xí)慣,提供建議應(yīng)該是高級(jí)開發(fā)人員工作的一部分。
理想情況下,審查時(shí)間應(yīng)該是開發(fā)團(tuán)隊(duì)核心流程的一部分,而對(duì)關(guān)鍵審查建議的總結(jié)也應(yīng)是每次會(huì)議的一部分。
平衡結(jié)構(gòu)與混沌
編寫太過整潔的代碼會(huì)浪費(fèi)時(shí)間和資源。編寫潦草的代碼比遭遇 Coder Block 而根本無法交付要好得多。
另一方面,潦草的代碼不靈活且難以維護(hù)。這五條規(guī)則將有助于使我們的代碼變得更整潔,且無需浪費(fèi)時(shí)間。正如生活的各方面一樣,好的事物都是在結(jié)構(gòu)和混亂的健康平衡中產(chǎn)生的。