|
“簡潔代碼”是我在寫代碼中一直以來遵循的一條理論。事實上,對于我來說,與其說是一種理論,不如說是一種信仰。他是這么一種理念——你的代碼必須夠簡潔且盡可能接近于完美。如果你所寫出來的代碼比你所需要的多,那么多出來的那部分代碼不應該存在其中。任何的多余都是不可能容忍的,而且一直以來我甚至覺得一個空格都不允許多余。你要讓你的代碼不僅僅是解決了問題,而是盡可能的有效率、可讀性好、易維護。同樣,我經(jīng)?;ê芏囝~外的時間去設計我的代碼。 所有的一切開始于 2001 年,當時我正在讀 Andy Hunt 和 Dave Thomas 寫的《程序員修煉之道》。讀到其中如“永遠不要接受一個壞了的窗口”之類的觀點時,讓我產生了共鳴。 這設想起來十分簡單。想象下,你有一間房子,然后因為沒有設計圖來修復它,墻面開始裂開,然后越來越嚴重,直到房頂坍塌?;蛘吣阌幸惠v購物手推車,你把它遺棄在街角,然后人們開始往里面扔垃圾。很快,整個推車都將塞滿垃圾直到溢出來。在以上兩種情況中,如果你不設定好清楚的界限和規(guī)則,長久之后你肯定會遇到問題。我以前入職過一家新公司,那里的團隊寫出很多臟代碼,在那里工作一點都不開心。我意識到,當人們開始變得懶惰,對自己的代碼毫無責任心時,問題就會累積。結果是,每一次有更新時,他們都要花不知道多少時間去進行一次次修改。沒有人需要這樣的代碼。 我把自己稱作是實用至上的完美主義者。這意味著,一方面,在特定情況下我解決問題時,使用的方法一般是合理并且恰當?shù)模皇且蕾囉谀:南敕ê屠碚?。另一方面,我希望我的代碼能夠在第一次就盡可能完美,不是我喜歡浪費時間,而是因為足夠節(jié)約,我知道這將在之后給我省下更多時間。 如何完成“簡潔代碼”設計 那么,該怎樣創(chuàng)造“簡潔代碼”呢?首先,你不能把你的項目當做一個代碼項目;你要把它想象成一個設計和計劃的過程。很多開發(fā)者經(jīng)常一頭猛扎進代碼中一頓亂敲,因為他們受到他們領導們或者其他人的要求完成盡快任務的壓力。相比之下,一個具有“簡潔代碼”編寫習慣的開發(fā)者,會盡量確保自己在開始敲代碼前已經(jīng)理解了問題的重點所在。想象下你正在建一棟房子,而你卻打算建一個薄弱的地基,如果你之后想要擴大你的房子,你將花費更多的時間和金錢去重筑地基。這就是為什么,對我來說,程序的第一步,就是和客戶方了解清楚,他需要的結果具體是什么樣的。 如果您遵循領域模型驅動設計,那么下一步讓代碼簡潔的方法是:創(chuàng)建共用語言或“領域通用語言”。 代碼的用詞非常重要,因為您希望您的變量名稱,類名稱和包名稱無論誰查看代碼都能理解。 現(xiàn)在有些開發(fā)者會說:“拜托,我們只用了一些愚蠢的名字,稍后再改?!?/p> 雖然這看起來是最快的解決辦法,但是團隊,甚至是編寫它的開發(fā)人員,可能會迷失在這些無意義的名字中。 代碼中的每個抽象詞語可能會給不同的團隊成員帶來不同的關于項目方向的概念, 如果我考慮編寫一個梨,而你考慮編寫一個蘋果,我們最終會得到一個無用的蘋果梨混合詞。 如果每個人都參與進來,從客戶到開發(fā)人員,在設計過程中進行良好的溝通,我們就開啟了這門與項目一起發(fā)展的通用的“無處不在的語言”。目標是一個完整的、可理解的程序,由整個團隊編寫,但看起來好像是由一個人編寫的。它應該由簡單的元素組合在一起,來傳達復雜的思想。我們應該避免模棱兩可的術語而傳達不了恰當?shù)睦斫?。以這種方式進行溝通將有助于我們預防問題,而不是以后再解決問題?,F(xiàn)在,我們可以確認客戶想要蘋果還是雪梨,最終達成客戶滿意的結果。在剛開始時花些時間討論,如果可以真正幫助選擇項目的進行方向 ,就可以為以后節(jié)省許多時間。 估算上的賭博 整潔編碼的難點之一是估算你的時間表。許多開發(fā)人員害怕對他們的經(jīng)理誠實,這就是為什么我認為信任你的經(jīng)理是很重要的。比方說你有一種直覺,認為一個項目需要十天,但是你害怕說“十天”,所以你會想:“嗯,如果我真地很努力,我加班,如果一切順利的話,我應該能在八天內完成這項工作?!?我稱之為估算上的賭博。于是,你就定下一個時間表,走到老板或客戶跟前說: “我會在八天內搞定它。”你猜怎么著?許多經(jīng)理會回你一句:“我給你四天時間!” 于是,一個你認為很可能要花十天時間的項目,如果沒有缺陷(bug)的話,現(xiàn)在變得幾乎沒有時間了,現(xiàn)在你很忙,以至于你無法顧及你本應該做到的代碼整潔。 通常,我把一切都考慮進去。如果我覺得一個項目需要十天,我通常會告訴我的客戶十五天。那不是說我一開始先花五天四處閑逛。我盡我最大的努力按我直覺的時間完成那個項目,但經(jīng)常發(fā)生的是,客戶改變需求,或者可能我最初的設計不可行,所以我需要那額外的五天。 對于開發(fā)人員來說,這是一件困難的事情,尤其是當你的同事聲稱他或她能在一半時間內完成。當然,也許他們會得到這份工作,但是,當結果是一坨屎時,你就會得到下一份工作。在一個靈活的團隊里,你的老板可能會讓你有額外的時間,如果你不能按時完成,但那也是在賭博。客戶很少會那么寬容。永遠不要賭你要花多少時間。你必須相信你自己,相信你的知識。 對我來說,做一個軟件工匠就是要有一種專注的態(tài)度,對你的代碼、工作和時間負責。所以,從開始討論到最終結果,你的一個焦點應該是保持你自己的高標準,盡可能為你的客戶創(chuàng)造最好的產品。 系統(tǒng)設計 好了,所以現(xiàn)在我們有了我們的遠景、共同語言和時間表,我們可以開始計劃我們的代碼了。我做這事的方法是在白板上畫方框,表示我們的系統(tǒng),以及我們系統(tǒng)的不同組件如何在一起工作。這樣做的目的是可視化我們的系統(tǒng)將如何運行,并討論使組件相互作用的最高效的方法。當你發(fā)現(xiàn)你的設計錯綜復雜,就要尋找方法來簡化,因為錯綜復雜的區(qū)域是缺陷(bug)和代碼崩潰的溫床。 現(xiàn)在,你有了自己的設計,但是你的同事呢?他開發(fā)相同系統(tǒng)的想法可能與你的完全不同,而這正是我們需要更多討論的地方。在小組工作時,我一向認為開發(fā)人員應該爭辯和討論他們的系統(tǒng)。這有助于提高系統(tǒng)的效率和效用。這也有助于保持統(tǒng)一的代碼遠景,并保持高昂的團隊精神,因為每個人都在一起工作。 我喜歡拿這些方框圖作為與客戶進一步溝通的機會。他們通常不懂代碼,但他們理解帶有商業(yè)術語注解的方框圖。你可以問他們:“這是你所想的嗎?” 并讓他們參與這個過程。這是許多開發(fā)人員未能利用的系統(tǒng)設計中最強大的方面之一,因為即使是不懂代碼的人,仍然能夠理解設計的總體概念。 當團隊之中或團隊與客戶之間出現(xiàn)分歧時,不要過于擔心。分歧是一個很好的征兆,意味著需要進一步的改進或調整,應該被看作是改善結果的機會,而不是威脅。這些征兆僅僅意味著你們在達成共識之前需要多說。一個輕量級的、基于團隊的開放討論是這里的關鍵方法。等級扁平的公司更容易促成這種討論??偸且M早讓客戶參與討論。有時,意見不同的原因可能是客戶不曉得他們的選擇會導致性能不佳、維護困難或成本高昂。所以,問他們:“我們現(xiàn)在真的需要這個功能嗎?如果需要,我們能簡化它嗎?” 從另一方面來看,開發(fā)者經(jīng)常沒有意識到,一些無法抗拒的商務因素往往會導致客戶把任務變得更加地復雜??蛻舴矫娼?jīng)常會提出一些不必要的需求,然后開發(fā)者們就嘗試滿足他們。但是我相信,開發(fā)者的工作不是這樣的,不要為了迎合客戶而盲目地接受用戶的需求,當你覺得某些需求不切實際的時候,應當主動說出來。戰(zhàn)勝分歧,需要雙方對彼此抱有足夠的尊重和信任。如果你能把自我放在一邊并促進這個過程,結果將會是雙贏。雙方都必須不斷問對方問題和挑戰(zhàn)對方觀點,直到達成共識。這樣一來,才能最大可能地為客戶創(chuàng)造出真正想要的產品。 除此之外,我經(jīng)常聽到開發(fā)者談及的一件事是,“哦,讓我們添加一些額外的功能,因為我們將來可能需要它?!庇肋h不要這樣做,這是無謂的時間浪費。更糟糕的是,它實際上是有害的。當你通過添加額外的功能來使代碼復雜化時,你將使代碼更難閱讀、理解、維護和測試。這樣做也容易在代碼中引入錯誤。所以,這些不必要的額外功能真的是有害的!你不知道未來如何,所以你的假設有 90% 的可能是錯誤的。即使是對的,但要用到該功能可能是在兩年之后的事情了,那時候,你可能已經(jīng)找到了一個更好的方法。 如果你正在建房子,一旦建好了地基,你決定添加一個額外的房間,這將花費大量的時間和金錢。另一方面,軟件是不同的。軟件可以以較低的成本進行迭代更改。改變它是不容易的,但這肯定比在一個房子上添加房間更容易一些。軟件架構的越好,就越容易,維護的成本就更便宜。作為程序員,簡單的代碼應該作為永遠的追求。 開始寫代碼 終于,經(jīng)過充分的設計之后,可以開始寫代碼了。你可以看到,在寫代碼之前,還是有很多事情需要做的,這就是“簡潔代碼”和“臟亂代碼”的區(qū)別——設計在前。 很多人經(jīng)常容易誤解,我已經(jīng)花了那么多時間來設計了,那么我的代碼就將馬上變得更好,只需要直截了當?shù)膶懗鰜砭涂梢粤?。其實并不是這樣。你仍然需要在編程過程中保持足夠的嚴謹和細心,并且盡可能的測試你的代碼。即便你認為你的設計是完美無瑕的,也仍然要這么做。軟件開發(fā)可不僅僅是做個快速設計然后寫幾行代碼這么簡單。 在一個理想狀況下,你應當從測試開始。如果可能的話,我推薦使用測試驅動開發(fā)方法,TDD。從實現(xiàn)具體業(yè)務目標的集成測試或者驗收測試開始,然后按照各個小的測試單元一項一項來。你應該在你寫完測試要求后,然后再開始寫代碼,只要你有一個科學的測試過程,重寫或者重構你的代碼都將十分簡便。 對于擁有非平坦型的組織結構的組織來說,這種“測試優(yōu)先”的方法是非常具有挑戰(zhàn)性的。為了能夠如此工作,一個組織需要基于開放溝通和迭代的實驗方法,而不是需要分層的、自上而下的管理風格。管理者需要完全信任他們的團隊,并將責任交給他們。 然而,在大多數(shù)仍然有許多恐懼和封閉的公司中,這仍然有很長的路要走。這種方法與當今大多數(shù)組織仍然存在的層級管理文化形成鮮明的對照。 因此,我們需要以小步驟開始,同時企盼公司能夠隨著時間的推移而發(fā)展。 一個小的步驟是用“測試優(yōu)先”方法來取代“測試最后”,最重要的是,在一天結束的時候最終的代碼是實際測試的代碼。測試將再次改進我們的要求,并允許我們專注于代碼的功能 - 即其設計和結構,而不是其在技術上的運作方式。開發(fā)人員需要謹記,他/她主要是為企業(yè)編碼,而不是為自己編寫,所以措辭需要非常清晰。開發(fā)人員之間的任何誤解都會導致錯誤??梢钥隙ǖ氖牵祟愬e誤不會引起你的代碼無法工作,但是當另一個開發(fā)人員試圖以你計劃以外的方式使用你的方法時,會導致進一步的錯誤。 我通常拿寫代碼和寫書進行比較。沒有作者會嚴格按照順序去寫,他們不會把前面的章節(jié)寫完美了才開始下面的部分。一般的作者總是從一個輪廓開始,之后再來改進每一頁,并不斷修正直至完美。在編碼上,經(jīng)過一輪測試并得出“代碼能工作”并不是好的代碼標準。你必須改進你的代碼直到它變得完美。如果代碼能工作了,你不僅僅要測試,你還要一直保證代碼盡可能明晰。 摘自開源中國,譯者 :圣潔之子, Tocy 英文原文:Clean Code Principles |
|
|