整潔之道,如何讓代碼更明確、簡單、有力
這篇文章摘錄自《代碼整潔之道》第一章,這本書被看作是程序員必讀的書籍之一。但好的書不只是交給你工具、技術(shù),更多是思維過程,近乎禪學(xué)、至理,這本書符合這樣的定義。本章技術(shù)元素最少,適合每一個(gè)領(lǐng)域的人閱讀。
閱讀本書有兩種原因:第一,你是個(gè)程序員;第二,你想成為更好的程序員。很好。我們需要更好的程序員。
這是本有關(guān)編寫好程序的書。它充斥著代碼。我們要從各個(gè)方向來考察這些代碼。從頂向下,從底往上,從里而外。讀完后,就能知道許多關(guān)于代碼的事了。而且,我們還能說出好代碼和糟糕的代碼之間的差異。我們將了解到如何寫出好代碼。我們也會(huì)知道,如何將糟糕的代碼改成好代碼。
1.1 要有代碼
有人也許會(huì)以為,關(guān)于代碼的書有點(diǎn)兒落后于時(shí)代-代碼不再是問題;我們應(yīng)當(dāng)關(guān)注模型和需求。確實(shí),有人說過我們正在臨近代碼的終結(jié)點(diǎn)。很快,代碼就會(huì)自動(dòng)產(chǎn)生出來,不需要再人工編寫。程序員完全沒用了,因?yàn)樯虅?wù)人士可以從規(guī)約直接生成程序。
扯淡!我們永遠(yuǎn)拋不掉代碼,因?yàn)榇a呈現(xiàn)了需求的細(xì)節(jié)。在某些層面上,這些細(xì)節(jié)無法被忽略或抽象,必須明確之。將需求明確到機(jī)器可以執(zhí)行的細(xì)節(jié)程度,就是編程要做的事。而這種規(guī)約正是代碼。
我期望語言的抽象程度繼續(xù)提升。我也期望領(lǐng)域特定語言的數(shù)量繼續(xù)增加。那會(huì)是好事一樁。但那終結(jié)不了代碼。實(shí)際上,在較高層次上用領(lǐng)域特定語言撰寫的規(guī)約也將是代碼!它也得嚴(yán)謹(jǐn)、精確、規(guī)范和詳細(xì),好讓機(jī)器理解和執(zhí)行。
那幫以為代碼終將消失的伙計(jì),就像是巴望著發(fā)現(xiàn)一種無規(guī)范數(shù)學(xué)的數(shù)學(xué)家們一般。他們巴望著,總有一天能創(chuàng)造出某種機(jī)器,我們只要想想、嘴都不用張就能叫它依計(jì)行事。那機(jī)器要能透徹理解我們,只有這樣,它才能把含糊不清的需求翻譯為可完美執(zhí)行的程序,精確滿足需求。
這種事永遠(yuǎn)不會(huì)發(fā)生。即便是人類,傾其全部的直覺和創(chuàng)造力,也造不出滿足客戶模糊感覺的成功系統(tǒng)來。如果說需求規(guī)約原則教給了我們什么,那就是歸置良好的需求就像代碼一樣正式,也能作為代碼的可執(zhí)行測試來使用。
記住,代碼確然是我們最終用來表達(dá)需求的那種語言。我們可以創(chuàng)造各種與需求接近的語言。我們可以創(chuàng)造幫助把需求解析和匯整為正式結(jié)構(gòu)的各種工具。然而,我們永遠(yuǎn)無法拋棄必要的精確性-所以代碼永存。
1.2 糟糕的代碼
最近我在讀Kent Beck著Implementation Patterns(中譯版《實(shí)現(xiàn)模式》) 一書的序言。他這樣寫道:"……本書基于一種不太牢靠的前提:好代碼的確重要……"這前提不牢靠?我反對!我認(rèn)為這是該領(lǐng)域最強(qiáng)固、最受支持、最被強(qiáng)調(diào)的前提了(我想Kent也知道)。我們知道好代碼重要,是因?yàn)槠涠倘睂?shí)在困擾了我們太久。
20世紀(jì)80年代末,有家公司寫了個(gè)很流行的殺手應(yīng)用,許多專業(yè)人士都買來用。然后,發(fā)布周期開始拉長。缺陷總是不能修復(fù)。裝載時(shí)間越來越久,崩潰的幾率也越來越大。至今我還記得自己在某天沮喪地關(guān)掉那個(gè)程序,從此再不用它。在那之后不久,該公司就關(guān)門大吉了。
20年后,我見到那家公司的一位早期雇員,問他當(dāng)年發(fā)生了什么事。他的回答叫我愈發(fā)恐懼起來。原來,當(dāng)時(shí)他們趕著推出產(chǎn)品,代碼寫得亂七八糟。特性越加越多,代碼也越來越爛,最后再也沒法管理這些代碼了。是糟糕的代碼毀了這家公司。
你是否曾為糟糕的代碼所深深困擾?如果你是位有點(diǎn)兒經(jīng)驗(yàn)的程序員,定然多次遇到過這類困境。我們有專用來形容這事的詞:沼澤(wading)。我們趟過代碼的水域。我們穿過灌木密布、瀑布暗藏的沼澤地。我們拼命想找到出路,期望有點(diǎn)什么線索能啟發(fā)我們到底發(fā)生了什么事;但目光所及,只是越來越多死氣沉沉的代碼。
你當(dāng)然曾為糟糕的代碼所困擾過。那么-為什么要寫糟糕的代碼呢?
是想快點(diǎn)完成嗎?是要趕時(shí)間嗎?有可能。或許你覺得自己要干好所需的時(shí)間不夠;假使花時(shí)間清理代碼,老板就會(huì)大發(fā)雷霆?;蛟S你只是不耐煩再搞這套程序,期望早點(diǎn)結(jié)束?;蛟S你看了看自己承諾要做的其他事,意識到得趕緊弄完手上的東西,好接著做下一件工作。這種事我們都干過。
我們都曾經(jīng)瞟一眼自己親手造成的混亂,決定棄之而不顧,走向新一天。我們都曾經(jīng)看到自己的爛程序居然能運(yùn)行,然后斷言能運(yùn)行的爛程序總比什么都沒有強(qiáng)。我們都曾經(jīng)說過有朝一日再回頭清理。當(dāng)然,在那些日子里,我們都沒聽過勒布朗(LeBlanc)法則:稍后等于永不(Later equals never)。
#p#
1.3 混亂的代價(jià)
只要你干過兩三年編程,就有可能曾被某人的糟糕的代碼絆倒過。如果你編程不止兩三年,也有可能被這種代碼拖過后腿。進(jìn)度延緩的程度會(huì)很嚴(yán)重。有些團(tuán)隊(duì)在項(xiàng)目初期進(jìn)展迅速,但有那么一兩年的時(shí)間卻慢如蝸行。對代碼的每次修改都影響到其他兩三處代碼。修改無小事。每次添加或修改代碼,都得對那堆扭紋柴了然于心,這樣才能往上扔更多的扭紋柴。這團(tuán)亂麻越來越大,再也無法理清,最后束手無策。
隨著混亂的增加,團(tuán)隊(duì)生產(chǎn)力也持續(xù)下降,趨向于零。當(dāng)生產(chǎn)力下降時(shí),管理層就只有一件事可做了:增加更多人手到項(xiàng)目中,期望提升生產(chǎn)力??墒切氯瞬⒉皇煜は到y(tǒng)的設(shè)計(jì)。他們搞不清楚什么樣的修改符合設(shè)計(jì)意圖,什么樣的修改違背設(shè)計(jì)意圖。而且,他們以及團(tuán)隊(duì)中的其他人都背負(fù)著提升生產(chǎn)力的可怕壓力。于是,他們制造更多的混亂,驅(qū)動(dòng)生產(chǎn)力向零那端不斷下降。
1.3.1 華麗新設(shè)計(jì)
最后,開發(fā)團(tuán)隊(duì)造反了,他們告訴管理層,再也無法在這令人生厭的代碼基礎(chǔ)上做開發(fā)。他們要求做全新的設(shè)計(jì)。管理層不愿意投入資源完全重啟爐灶,但他們也不能否認(rèn)生產(chǎn)力低得可怕。他們只好同意開發(fā)者的要求,授權(quán)去做一套看上去很美的華麗新設(shè)計(jì)。
于是就組建了一支新軍。誰都想加入這個(gè)團(tuán)隊(duì),因?yàn)樗菑埌准?。他們可以重新來過,搞出點(diǎn)真正漂亮的東西來。但只有最優(yōu)秀、最聰明的家伙被選中。其余人等則繼續(xù)維護(hù)現(xiàn)有系統(tǒng)。
現(xiàn)在有兩支隊(duì)伍在競賽了。新團(tuán)隊(duì)必須搭建一套新系統(tǒng),要能實(shí)現(xiàn)舊系統(tǒng)的所有功能。另外,還得跟上對舊系統(tǒng)的持續(xù)改動(dòng)。在新系統(tǒng)功能足以抗衡舊系統(tǒng)之前,管理層不會(huì)替換掉舊系統(tǒng)。
競賽可能會(huì)持續(xù)極長時(shí)間。我就見過延續(xù)了十年之久的。到了完成的時(shí)候,新團(tuán)隊(duì)的老成員早已不知去向,而現(xiàn)有成員則要求重新設(shè)計(jì)一套新系統(tǒng),因?yàn)檫@套系統(tǒng)太爛了。
假使你經(jīng)歷過哪怕是一小段我談到的這種事,那么你一定知道,花時(shí)間保持代碼整潔不但有關(guān)效率,還有關(guān)生存。
1.3.2 態(tài)度
你是否遇到過某種嚴(yán)重到要花數(shù)個(gè)星期來做本來只需數(shù)小時(shí)即可完成的事的混亂狀況?你是否見過本來只需做一行修改,結(jié)果卻涉及上百個(gè)模塊的情況?這種事太常見了。
怎么會(huì)發(fā)生這種事?為什么好代碼會(huì)這么快就變質(zhì)成糟糕的代碼?理由多得很。我們抱怨需求變化背離了初期設(shè)計(jì)。我們哀嘆進(jìn)度太緊張,沒法干好活。我們把問題歸咎于那些愚蠢的經(jīng)理、苛求的用戶、沒用的營銷方式和那些電話消毒劑。不過,親愛的呆伯特(Dilbert) ,我們是自作自受 。我們太不專業(yè)了。
這話可不太中聽。怎么會(huì)是自作自受呢?難道不關(guān)需求的事?難道不關(guān)進(jìn)度的事?難道不關(guān)那些蠢經(jīng)理和沒用的營銷手段的事?難道他們就不該負(fù)點(diǎn)責(zé)嗎?
不。經(jīng)理和營銷人員指望從我們這里得到必須的信息,然后才能做出承諾和保證;即便他們沒開口問,我們也不該羞于告知自己的想法。用戶指望我們驗(yàn)證需求是否都在系統(tǒng)中實(shí)現(xiàn)了。項(xiàng)目經(jīng)理指望我們遵守進(jìn)度。我們與項(xiàng)目的規(guī)劃脫不了干系,對失敗負(fù)有極大的責(zé)任;特別是當(dāng)失敗與糟糕的代碼有關(guān)時(shí)尤為如此!
"且慢!"你說。"不聽經(jīng)理的,我就會(huì)被炒魷魚。"多半不會(huì)。多數(shù)經(jīng)理想要知道實(shí)情,即便他們看起來不喜歡實(shí)情。多數(shù)經(jīng)理想要好代碼,即便他們總是癡纏于進(jìn)度。他們會(huì)奮力衛(wèi)護(hù)進(jìn)度和需求;那是他們該干的。你則當(dāng)以同等的熱情衛(wèi)護(hù)代碼。
再說明白些,假使你是位醫(yī)生,病人請求你在給他做手術(shù)前別洗手,因?yàn)槟菚?huì)花太多時(shí)間,你會(huì)照辦嗎 ?本該是病人說了算;但醫(yī)生卻絕對應(yīng)該拒絕遵從。為什么?因?yàn)獒t(yī)生比病人更了解疾病和感染的風(fēng)險(xiǎn)。醫(yī)生如果按病人說的辦,就是一種不專業(yè)的態(tài)度(更別說是犯罪了)。
同理,程序員遵從不了解混亂風(fēng)險(xiǎn)的經(jīng)理的意愿,也是不專業(yè)的做法。
1.3.3 迷題
程序員面臨著一種基礎(chǔ)價(jià)值謎題。有那么幾年經(jīng)驗(yàn)的開發(fā)者都知道,之前的混亂拖了自己的后腿。但開發(fā)者們背負(fù)期限的壓力,只好制造混亂。簡言之,他們沒花時(shí)間讓自己做得更快!
真正的專業(yè)人士明白,這道謎題的第二部分說錯(cuò)了。制造混亂無助于趕上期限?;靵y只會(huì)立刻拖慢你,叫你錯(cuò)過期限。趕上期限的唯一方法-做得快的唯一方法 -就是始終盡可能保持代碼整潔。
1.3.4 整潔代碼的藝術(shù)
假設(shè)你相信混亂的代碼是禍?zhǔn)?,假設(shè)你接受做得快的唯一方法是保持代碼整潔的說法,你一定會(huì)自問:"我怎么才能寫出整潔的代碼?"不過,如果你不明白整潔對代碼有何意義,嘗試去寫整潔代碼就毫無所益!
壞消息是寫整潔代碼很像是繪畫。多數(shù)人都知道一幅畫是好還是壞。但能分辨優(yōu)劣并不表示懂得繪畫。能分辨整潔代碼和骯臟代碼,也不意味著會(huì)寫整潔代碼!
寫整潔代碼,需要遵循大量的小技巧,貫徹刻苦習(xí)得的"整潔感"。這種"代碼感"就是關(guān)鍵所在。有些人生而有之。有些人費(fèi)點(diǎn)勁才能得到。它不僅讓我們看到代碼的優(yōu)劣,還予我們以借戒規(guī)之力化劣為優(yōu)的攻略。
缺乏"代碼感"的程序員,看混亂是混亂,無處著手。有"代碼感"的程序員能從混亂中看出其他的可能與變化。"代碼感"幫助程序員選出最好的方案,并指導(dǎo)程序員制訂修改行動(dòng)計(jì)劃,按圖索驥。
簡言之,編寫整潔代碼的程序員就像是藝術(shù)家,他能用一系列變換把一塊白板變作由優(yōu)雅代碼構(gòu)成的系統(tǒng)。
1.3.5 什么是整潔代碼
有多少程序員,就有多少定義。所以我只詢問了一些非常知名且經(jīng)驗(yàn)豐富的程序員。
Bjarne Stroustrup,C++語言發(fā)明者,C++ Programming Language(中譯版《C++程序設(shè)計(jì)語言》)一書作者。
我喜歡優(yōu)雅和高效的代碼。代碼邏輯應(yīng)當(dāng)直截了當(dāng),叫缺陷難以隱藏;盡量減少依賴關(guān)系,使之便于維護(hù);依據(jù)某種分層戰(zhàn)略完善錯(cuò)誤處理代碼;性能調(diào)至最優(yōu),省得引誘別人做沒規(guī)矩的優(yōu)化,搞出一堆混亂來。整潔的代碼只做好一件事。
Bjarne 用了"優(yōu)雅"一詞。說得好!我MacBook上的詞典提供了如下定義:外表或舉止上令人愉悅的優(yōu)美和雅觀;令人愉悅的精致和簡單。注意對"愉悅"一詞的強(qiáng)調(diào)。Bjarne顯然認(rèn)為整潔的代碼讀起來令人愉悅。讀這種代碼,就像見到手工精美的音樂盒或者設(shè)計(jì)精良的汽車一般,讓你會(huì)心一笑。
Bjarne 也提到效率-而且兩次提及。這話出自C++發(fā)明者之口,或許并不出奇;不過我認(rèn)為并非是在單純追求速度。被浪費(fèi)掉的運(yùn)算周期并不雅觀,并不令人愉悅。留意 Bjarne怎么描述那種不雅觀的結(jié)果。他用了"引誘"這個(gè)詞。誠哉斯言。糟糕的代碼引發(fā)混亂!別人修改糟糕的代碼時(shí),往往會(huì)越改越爛。
務(wù)實(shí)的Dave Thomas和Andy Hunt從另一角度闡述了這種情況。他們提到破窗理論 。窗戶破損了的建筑讓人覺得似乎無人照管。于是別人也再不關(guān)心。他們放任窗戶繼續(xù)破損。最終自己也參加破壞活動(dòng),在外墻上涂鴉,任垃圾堆積。一扇破損的窗戶開辟了大廈走向傾頹的道路。
Bjarne也提到完善錯(cuò)誤處理代碼。往深處說就是在細(xì)節(jié)上花心思。敷衍了事的錯(cuò)誤處理代碼只是程序員忽視細(xì)節(jié)的一種表現(xiàn)。此外還有內(nèi)存泄漏,還有競態(tài)條件代碼。還有前后不一致的命名方式。結(jié)果就是凸現(xiàn)出整潔代碼對細(xì)節(jié)的重視。
Bjarne 以"整潔的代碼只做好一件事"結(jié)束論斷。毋庸置疑,軟件設(shè)計(jì)的許多原則最終都會(huì)歸結(jié)為這句警語。有那么多人發(fā)表過類似的言論。糟糕的代碼想做太多事,它意圖混亂、目的含混。整潔的代碼力求集中。每個(gè)函數(shù)、每個(gè)類和每個(gè)模塊都全神貫注于一事,完全不受四周細(xì)節(jié)的干擾和污染。
Grady Booch,Object Oriented Analysis and Design with Applications(中譯版《面向?qū)ο蠓治雠c設(shè)計(jì)》)一書作者。
整潔的代碼簡單直接。整潔的代碼如同優(yōu)美的散文。整潔的代碼從不隱藏設(shè)計(jì)者的意圖,充滿了干凈利落的抽象和直截了當(dāng)?shù)目刂普Z句。
Grady 的觀點(diǎn)與Bjarne的觀點(diǎn)有類似之處,但他從可讀性的角度來定義。我特別喜歡"整潔的代碼如同優(yōu)美的散文"這種看法。想想你讀過的某本好書?;貞浺幌?,那些文字是如何在腦中形成影像!就像是看了場電影,對吧?還不止!你還看到那些人物,聽到那些聲音,體驗(yàn)到那些喜怒哀樂。
閱讀整潔的代碼和閱讀Lord of the Rings(中譯版《指環(huán)王》)自然不同。不過,仍有可類比之處。如同一本好的小說般,整潔的代碼應(yīng)當(dāng)明確地展現(xiàn)出要解決問題的張力。它應(yīng)當(dāng)將這種張力推至高潮,以某種顯而易見的方案解決問題和張力,使讀者發(fā)出"啊哈!本當(dāng)如此!"的感嘆。
竊以為Grady所謂"干凈利落的抽象" (crisp abstraction),乃是絕妙的矛盾修辭法。畢竟crisp幾乎就是"具體"(concrete)的同義詞。我MacBook上的詞典這樣定義 crisp一詞:果斷決絕,就事論事,沒有猶豫或不必要的細(xì)節(jié)。盡管有兩種不同的定義,該詞還是承載了有力的信息。代碼應(yīng)當(dāng)講述事實(shí),不引人猜測。它只該包含必需之物。讀者應(yīng)當(dāng)感受到我們的果斷決絕。
"老大"Dave Thomas,OTI公司創(chuàng)始人,Eclipse戰(zhàn)略教父。
整潔的代碼應(yīng)可由作者之外的開發(fā)者閱讀和增補(bǔ)。它應(yīng)當(dāng)有單元測試和驗(yàn)收測試。它使用有意義的命名。它只提供一種而非多種做一件事的途徑。它只有盡量少的依賴關(guān)系,而且要明確地定義和提供清晰、盡量少的API。代碼應(yīng)通過其字面表達(dá)含義,因?yàn)椴煌恼Z言導(dǎo)致并非所有必需信息均可通過代碼自身清晰表達(dá)。
Dave老大在可讀性上和Grady持相同觀點(diǎn),但有一個(gè)重要的不同之處。Dave斷言,整潔的代碼便于其他人加以增補(bǔ)。這看似顯而易見,但亦不可過分強(qiáng)調(diào)。畢竟易讀的代碼和易修改的代碼之間還是有區(qū)別的。
Dave 將整潔系于測試之上!要在十年之前,這會(huì)讓人大跌眼鏡。但測試驅(qū)動(dòng)開發(fā)(Test Driven Development)已在行業(yè)中造成了深遠(yuǎn)影響,成為基礎(chǔ)規(guī)程之一。Dave說得對。沒有測試的代碼不干凈。不管它有多優(yōu)雅,不管有多可讀、多易理解,微乎測試,其不潔亦可知也。
Dave兩次提及"盡量少"。顯然,他推崇小塊的代碼。實(shí)際上,從有軟件起人們就在反復(fù)強(qiáng)調(diào)這一點(diǎn)。越小越好。
Dave也提到,代碼應(yīng)在字面上表達(dá)其含義。這一觀點(diǎn)源自Knuth的"字面編程"(literate programming) 。結(jié)論就是應(yīng)當(dāng)用人類可讀的方式來寫代碼。
Michael Feathers,Working Effectively with Legacy Code(中譯版《修改代碼的藝術(shù)》)一書作者。
我可以列出我留意到的整潔代碼的所有特點(diǎn),但其中有一條是根本性的。整潔的代碼總是看起來像是某位特別在意它的人寫的。幾乎沒有改進(jìn)的余地。代碼作者什么都想到了,如果你企圖改進(jìn)它,總會(huì)回到原點(diǎn),贊嘆某人留給你的代碼-全心投入的某人留下的代碼。
一言以蔽之:在意。這就是本書的題旨所在?;蛟S該加個(gè)副標(biāo)題,如何在意代碼。
Michael一針見血。整潔代碼就是作者著力照料的代碼。有人曾花時(shí)間讓它保持簡單有序。他們適當(dāng)?shù)仃P(guān)注到了細(xì)節(jié)。他們在意過。
Ron Jeffries,Extreme Programming Installed(中譯版《極限編程實(shí)施》)以及Extreme Programming Adventures in C#(中譯版《C#極限編程探險(xiǎn)》)作者。
Ron初入行就在戰(zhàn)略空軍司令部(Strategic Air Command)編寫Fortran程序,此后幾乎在每種機(jī)器上編寫過每種語言的代碼。他的言論值得咀嚼。
近年來,我開始研究貝克的簡單代碼規(guī)則,差不多也都琢磨透了。簡單代碼,依其重要順序:
-
能通過所有測試;
-
沒有重復(fù)代碼;
-
體現(xiàn)系統(tǒng)中的全部設(shè)計(jì)理念;
-
包括盡量少的實(shí)體,比如類、方法、函數(shù)等。
在以上諸項(xiàng)中,我最在意代碼重復(fù)。如果同一段代碼反復(fù)出現(xiàn),就表示某種想法未在代碼中得到良好的體現(xiàn)。我盡力去找出到底那是什么,然后再盡力更清晰地表達(dá)出來。
在我看來,有意義的命名是體現(xiàn)表達(dá)力的一種方式,我往往會(huì)修改好幾次才會(huì)定下名字來。借助Eclipse這樣的現(xiàn)代編碼工具,重命名代價(jià)極低,所以我無所顧忌。然而,表達(dá)力還不只體現(xiàn)在命名上。我也會(huì)檢查對象或方法是否想做的事太多。如果對象功能太多,最好是切分為兩個(gè)或多個(gè)對象。如果方法功能太多,我總是使用抽取手段(Extract Method)重構(gòu)之,從而得到一個(gè)能較為清晰地說明自身功能的方法,以及另外數(shù)個(gè)說明如何實(shí)現(xiàn)這些功能的方法。
消除重復(fù)和提高表達(dá)力讓我在整潔代碼方面獲益良多,只要銘記這兩點(diǎn),改進(jìn)臟代碼時(shí)就會(huì)大有不同。不過,我時(shí)常關(guān)注的另一規(guī)則就不太好解釋了。
這么多年下來,我發(fā)現(xiàn)所有程序都由極為相似的元素構(gòu)成。例如"在集合中查找某物"。不管是雇員記錄數(shù)據(jù)庫還是名-值對哈希表,或者某類條目的數(shù)組,我們都會(huì)發(fā)現(xiàn)自己想要從集合中找到某一特定條目。一旦出現(xiàn)這種情況,我通常會(huì)把實(shí)現(xiàn)手段封裝到更抽象的方法或類中。這樣做好處多多。
可以先用某種簡單的手段,比如哈希表來實(shí)現(xiàn)這一功能,由于對搜索功能的引用指向了我那個(gè)小小的抽象,就能隨需應(yīng)變,修改實(shí)現(xiàn)手段。這樣就既能快速前進(jìn),又能為未來的修改預(yù)留余地。
另外,該集合抽象常常提醒我留意"真正"在發(fā)生的事,避免隨意實(shí)現(xiàn)集合行為,因?yàn)槲艺嬲枰牟贿^是某種簡單的查找手段。
減少重復(fù)代碼,提高表達(dá)力,提早構(gòu)建簡單抽象。這就是我寫整潔代碼的方法。
Ron以寥寥數(shù)段文字概括了本書的全部內(nèi)容。不要重復(fù)代碼,只做一件事,表達(dá)力,小規(guī)模抽象。該有的都有了。
Ward Cunningham,Wiki發(fā)明者,eXtreme Programming(極限編程)的創(chuàng)始人之一,Smalltalk語言和面向?qū)ο蟮乃枷腩I(lǐng)袖。所有在意代碼者的教父。
如果每個(gè)例程都讓你感到深合己意,那就是整潔代碼。如果代碼讓編程語言看起來像是專為解決那個(gè)問題而存在,就可以稱之為漂亮的代碼。
這種說法很Ward。它教你聽了之后就點(diǎn)頭,然后繼續(xù)聽下去。如此在理,如此淺顯,絕不故作高深。你大概以為此言深合己意吧。再走近點(diǎn)看看。
"…… 深合己意"。你最近一次看到深合己意的模塊是什么時(shí)候?模塊多半都繁復(fù)難解吧?難道沒有觸犯規(guī)則嗎?你不是也曾掙扎著想抓住些從整個(gè)系統(tǒng)中散落而出的線索,編織進(jìn)你在讀的那個(gè)模塊嗎?你最近一次讀到某段代碼、并且如同對Ward的說法點(diǎn)頭一般對這段代碼點(diǎn)頭,是什么時(shí)候的事了?
Ward期望你不會(huì)為整潔代碼所震驚。你無需花太多力氣。那代碼就是深合你意。它明確、簡單、有力。每個(gè)模塊都為下一個(gè)模塊做好準(zhǔn)備。每個(gè)模塊都告訴你下一個(gè)模塊會(huì)是怎樣的。整潔的程序好到你根本不會(huì)注意到它。設(shè)計(jì)者把它做得像一切其他設(shè)計(jì)般簡單。
那 Ward有關(guān)"美"的說法又如何呢?我們都曾面臨語言不是為要解決的問題所設(shè)計(jì)的困境。但Ward的說法又把球踢回我們這邊。他說,漂亮的代碼讓編程語言像是專為解決那個(gè)問題而存在!所以,讓語言變得簡單的責(zé)任就在我們身上了!當(dāng)心,語言是冥頑不化的!是程序員讓語言顯得簡單。
1.8 小結(jié)
藝術(shù)書并不保證你讀過之后能成為藝術(shù)家,只能告訴你其他藝術(shù)家用過的工具、技術(shù)和思維過程。本書同樣也不擔(dān)保讓你成為好程序員。它不擔(dān)保能給你"代碼感"。它所能做的,只是展示好程序員的思維過程,還有他們使用的技巧、技術(shù)和工具。
和藝術(shù)書一樣,本書也充滿了細(xì)節(jié)。代碼會(huì)很多。你會(huì)看到好代碼,也會(huì)看到糟糕的代碼。你會(huì)看到糟糕的代碼如何轉(zhuǎn)化為好代碼。你會(huì)看到啟發(fā)、規(guī)條和技巧的列表。你會(huì)看到一個(gè)又一個(gè)例子。但最終結(jié)果取決于你自己。