不要浪費(fèi)時(shí)間寫完美代碼
一個(gè)系統(tǒng)可以維持5年,10年,甚至20年以上,但是代碼和設(shè)計(jì)模式的生命周期非常短,當(dāng)對(duì)一個(gè)解決方案使用不同的方法進(jìn)行迭代的時(shí)候,通常只能維持?jǐn)?shù)月,數(shù)日,甚至幾分鐘的時(shí)間。
代碼重要性區(qū)分
隨著對(duì)代碼是如何改變的研究,致力于代碼修改藝術(shù)的人發(fā)現(xiàn)了一個(gè)代碼庫(kù)的規(guī)律曲線。每個(gè)系統(tǒng)都有很多從未改變的代碼。但是也有小部分非常重要且有用的代碼一次又一次的改變,經(jīng)過(guò)了多次重構(gòu)和重寫。
當(dāng)你對(duì)一個(gè)系統(tǒng),問(wèn)題域,或者架構(gòu)方法越來(lái)越熟悉的時(shí)候,就更容易發(fā)現(xiàn)和預(yù)測(cè)哪些代碼會(huì)經(jīng)常修改,哪些代碼不會(huì)被修改,即區(qū)分重要代碼和非重要代碼。
我們應(yīng)該嘗試追求完美代碼?
眾所周知,我們應(yīng)該寫干凈整潔的代碼,而干凈整潔就應(yīng)該是盡可能一致,易懂,簡(jiǎn)單。
有些人追求極致,強(qiáng)迫自己寫的代碼要漂亮且優(yōu)雅,接近于他們所能達(dá)到的完美,瘋狂的進(jìn)行重構(gòu),并致力于每一個(gè)細(xì)節(jié)。
與寫完代碼不再變動(dòng)相比,一直修改的代碼會(huì)讓完美的需求和具有前瞻性的設(shè)計(jì)變得有些多余和沒必要。
你不能寫出完美的軟件,這樣的結(jié)果會(huì)使你受傷了?沒必要,把它當(dāng)做人生格言,信奉并祝賀,因?yàn)橥昝赖能浖⒉淮嬖?,在?jì)算機(jī)歷史中沒一個(gè)人曾經(jīng)寫出過(guò)完美軟件,當(dāng)然,你也不可能成為第一個(gè),只有接受這樣一個(gè)事實(shí),你才能不再在浪費(fèi)時(shí)間,將精力放在可能實(shí)現(xiàn)的理想中。
Andrew Hunt, 實(shí)用程序員:從路人到大師
曾經(jīng)寫過(guò)的代碼不需要優(yōu)美優(yōu)雅。它必須是正確的且容易理解的,因?yàn)樵谙到y(tǒng)的生命周期中那些從不用修改的代碼也會(huì)被多次訪問(wèn)。同樣這些代碼不需要又整潔又緊湊——只要整潔就足夠了。在一定程度上, 復(fù)制粘貼 和其他快捷方法寫出的代碼是允許的。 即使這些代碼周圍的代碼變了, 這些代碼不需要反復(fù)修改,不需要重構(gòu)(直到你需要修改它)。這樣的代碼是不值得花費(fèi)額外的時(shí)間的。
那些經(jīng)常修改的代碼該如何處理呢?苦思冥想代碼風(fēng)格和提出最優(yōu)雅的解決方案是浪費(fèi)時(shí)間的,因?yàn)檫@些代碼可能會(huì)在幾天或幾周之內(nèi)再次修改,甚至重寫。因?yàn)橄Ma應(yīng)該變得更好而 癡迷地重構(gòu) 那些需要經(jīng)常修改代碼,或者重構(gòu)那些基本不會(huì)修改的代碼。代碼一直可以變得更好,但這并不重要。
最重要的是:代碼是否做到了它應(yīng)該做的事?代碼運(yùn)行正確且可用又高效嗎?能夠 處理錯(cuò)誤和錯(cuò)誤數(shù)據(jù) 而不奔潰或者至少是 安全地出錯(cuò) 嗎?容易調(diào)試嗎?能簡(jiǎn)單又安全地修改代碼嗎?這些不是對(duì)于完美代碼的主觀想法,而是用來(lái)區(qū)分成功和失敗的切實(shí)可行的措施。
實(shí)用的編碼和重構(gòu)
精益開發(fā)的核心思想是:不要浪費(fèi)時(shí)間在那些不重要的事情上。這句話已告訴我們?cè)撛鯓訉懘a,怎樣重構(gòu)代碼,怎樣評(píng)審代碼,怎樣測(cè)試代碼。
為了把工作做好, 只重構(gòu)你需要的 —— Martin Fowler 稱為機(jī)會(huì)主義重構(gòu)(理解、清理不切實(shí)際的東西)和預(yù)先重構(gòu)。足夠讓修改變得更簡(jiǎn)單更安全即可,其他的不必考慮。如果你不修改那些代碼,那么那些代碼長(zhǎng)什么樣子是無(wú)所謂的事。
在代碼評(píng)審中, 只關(guān)注那些重要的 。代碼正確嗎?有防范機(jī)制嗎?安全嗎?容易理解嗎?能夠安全地修改嗎?
忘掉編碼風(fēng)格(除非編碼風(fēng)格達(dá)到可理解的程度)。讓你的 IDE 處理格式化。不要過(guò)多爭(zhēng)論:代碼是否可以是“更多的OO”。只要它有意義,不管它是否適當(dāng)?shù)刈裱@種或那種模式,這些都不重要。無(wú)論你喜歡還是不喜歡都沒關(guān)系。無(wú)論你能否以更好的方式做到這一點(diǎn)并不重要——除非你在教一個(gè)對(duì)平臺(tái)和語(yǔ)言都不熟悉的新手,而且你需要做一些代碼評(píng)審作為指導(dǎo)的一部分。
寫測(cè)試是有必要的。測(cè)試那些涵蓋主路徑和重要例外情況的測(cè)試。測(cè)試可以讓你以最少的工作量獲得最多的自信心。 大規(guī)模全范圍測(cè)試或者小規(guī)模局部測(cè)試 ——在編寫代碼之前測(cè)試還是之后測(cè)試,都沒關(guān)系,只要做了這個(gè)工作就行。
這不(僅)是關(guān)于代碼
建筑學(xué)和工程學(xué)的隱喻從未在軟件開發(fā)中生效。我們不是設(shè)計(jì)和建造橋梁或摩天大樓 —— 它們會(huì)在幾年或幾代內(nèi)保持基本相同。我們正在建造一些更富有創(chuàng)造力和抽象性、更加短暫的東西。代碼編寫之后是用來(lái)修改的 —— 這就是為什么它被稱為“軟件”的原因。
“經(jīng)過(guò)五年的使用和修改,成功的軟件的源碼通常與最初版本完全不一樣,而五年之后的成功的建筑幾乎沒有什么變化。”
Kevin Tate, 可持續(xù)軟件開發(fā)
我們需要將代碼看作是我們工作的一個(gè)暫存:
…有時(shí)在面對(duì)更重要的事情時(shí),我們被引導(dǎo)到盲目崇拜代碼。我們經(jīng)常會(huì)處于這樣的幻象中:在移交產(chǎn)品時(shí)最有價(jià)值的東西是代碼,實(shí)際上這可能是對(duì)問(wèn)題域的理解、設(shè)計(jì)難題的進(jìn)展甚至是客戶反饋。
Dan Grover, 代碼和創(chuàng)造性破壞
迭代開發(fā)教會(huì)了我們通過(guò)實(shí)驗(yàn)來(lái)驗(yàn)證我們工作的結(jié)果 —— 我們是否已解決了這個(gè)問(wèn)題,如果沒有,我們學(xué)到了什么,我們?cè)撊绾胃倪M(jìn)?我們正在構(gòu)建的軟件永遠(yuǎn)不會(huì)完成。即使設(shè)計(jì)和代碼是正確的,它們可能也只是在一段時(shí)間內(nèi)是正確的,直到環(huán)境要求其再次改動(dòng)或被替換為更好的東西。
我們需要編寫好的代碼:可理解、正確、安全和可靠的代碼。我們需要重構(gòu)和審查它,并寫出好的有用的測(cè)試用例,直到其中的一些代碼(也可能是全部(),可能會(huì)很快被拋棄,或者可能永遠(yuǎn)不會(huì)被再次看到,或根本不會(huì)使用了。我們需要認(rèn)識(shí)到,我們的一些工作必然會(huì)被浪費(fèi)掉,并要為此進(jìn)行優(yōu)化。做那些必須做的,不做無(wú)用功。不要浪費(fèi)時(shí)間嘗試編寫完美的代碼。