|
1,定義
讓我們來談談代碼。
代碼重要嗎?當然,代碼就是設計(Jack W.Reeves, 1992);代碼是最有價值的交付物。
我們需要好代碼嗎?在給“好代碼”下個定義之前,這個問題無法回答。
那么,究竟什么是好代碼?
聞到硝煙味了嗎?哦不,戰爭從來不是好東西。
對我而言,好代碼就是 “整潔可用” 的代碼。
好代碼首先必須是“可用”的代碼,“可用” 是指代碼做了它應該做的事情,而且做得不錯。 如果讓你寫求絕對值的代碼,你就不能寫成求平方根的;如果讓你做一個文本編輯器,OK,你做出來了,它不是一個圖片編輯器,它確確實實就是一個文本編輯器。但是用戶輸入一個字要一分鐘,這也不能稱之為“可用”,因為它沒達到“不錯”的標準,當然,如果這個文本編輯器是給“慢星人”用的,你有理由認為它是 “不錯”的。那么,究竟怎樣才叫“應該做”,怎樣才叫“不錯”呢?也許客戶(用戶)的反應(評價)是唯一的標準答案。
其次它需要整潔。
整潔是一個相對的詞,在我看來,它唯一的作用就是令維護簡單。如果你寫的代碼不需維護(沒有BUG、完成之后永遠不會做功能改動、沒有任何其它代碼基于這些代碼編寫等等,顯然,如果滿足了這些條件,沒人“有必要”來閱讀你的代碼),比如用完即拋的很簡單的一次性用品,那么只要“可用”就行了,不需要“整潔”。值得注意的是, 這里隱含了一個假設的前提條件:不保持代碼整潔的情況下,你能夠寫出“可用”的代碼。
現實生活中相當一部分(也許我可以說大部分)代碼是需要維護的,也就意味著它們如果想成為好代碼,必須要整潔。
在繼續探討“整潔”話題之前,也許有必要先談談“復雜度”。
2,復雜度
什么是復雜度? 在本文中,我們所談及的復雜度是指軟件開發中的復雜度,很難給出精確的數學定義,雖然業界已經有了各種相對嚴格的測量方法,但根據本文需要,這里只簡單的給出自己的定義:復雜度是事物復雜程度的量化描述,其大概等價于使軟件達到可用所需耗費的勞動(智力+體力)的總和。
當然,上述定義又引出了對“勞動”的量化需求,本文更多的只需要對“復雜度“做相對的評估,不需要絕對的量化,所以這里簡單地用通用的行業描述:勞動 = 人月。
無疑,(現有事實證明)軟件開發是復雜度很高的活動,我們有各種方法論、工具、最佳實踐等等等,其本質都是為了降低軟件開發的復雜度,也就是:第一,使軟件達到可用的標準;第二,盡可能地減少所需勞動。
那么,軟件開發為什么這么復雜呢?《沒有銀彈》給出了它的回答:所有軟件活動包括根本任務——打造由抽象軟件實體構成的復雜(現實)概念結構,次要任務——使用編程語言表達這些抽象實體,在時間和空間限制內將它們映射成機器語言。相應的,軟件開發的復雜度由兩部分構成:
1) 來自根本任務:根本困難——對復雜現實情況的抽象,這是軟件開發中固有的困難。
2) 來自次要任務:次要困難——通過特定表達方式讓計算機理解。這是受限于目前生產(方法、工具)的并非與生俱來的困難。
更具體一些,軟件的復雜度來自這些:
1) 規模:軟件實體可能比人類有史以來創造的其他任何實體都要復雜,計算機本身就比人類建造的大多數東西復雜,它擁有大量狀態,這使得構思、描述和測試都很困難,而軟件系統狀態又比計算機狀態多幾個數量級。同時,軟件沒有兩個部分是相同的,至少在語句級別上,如果有,我們會將它合并成一個子函數,在這個方面,軟件系統和建筑、汽車大不相同,后者存在大量重復的部分。另外它不僅僅導致技術上的困難,還引發了許多管理上的問題,它使全面理解變得很困難,從而妨礙了概念上的 完整性;它使所有離散出口難以尋找和控制;它引發了大量學習和理解上的負擔,使開發慢慢地演變成一場災難。
2)(容易)變化:軟件天生就是易變的,第一,因為人們的想法本身容易產生變化;第二,人們可能有這樣的錯覺:軟件很容易變化——不需要太高的代價,相對其他產品來說;第三,軟件必須演變才能成功。軟件實體的擴展不是簡單元素的重復添加,而必須是不同元素實體的添加,大多數情況下,這些元素以非線性遞增的方式交互,因此整個軟件的復雜度以更大的非線性級數增長。
3)(缺乏)一致性:物理學家和數學家都堅信本源的存在,所有復雜的表象之下都必有簡單的一致的本源存在,如基本粒子,如通用原理。軟件工程師可能缺乏這種信念,他必須處理不同用戶習慣以及隨時間推移而變化的接口,這些變化是無規律的,僅僅由于不同的人——而不是上帝——設計的結果;另外他們還需要處理各種歷史遺留系統的兼容性所帶來的問題,這往往需要保持接口和歷史接口的一致性。從本質上來說,這些都是不必要的,但軟件工程師必須處理它們——以及它們帶來的復雜度。
4) 不可見性:幾何抽象是強大的工具,建筑平面圖、機械制圖、分子模型都幫助相關工作人員更好的理解及工作,軟件的客觀存在不具有空間的形體特性,因此沒有已有的表達方式能恰如其分的描述軟件。當我們試圖用圖形描述軟件結構時,我們發現它不止包含一個,而是很多相互關聯、重疊在一起的圖形,現有的描述方式都是強制將關聯分割,直到可以層次化一個或多個圖形(形成某種扁平結構)。這種缺憾限制了個人的設計過程,同時也嚴重阻礙了相互之間的交流。
3,整潔
日常生活中我們談起整潔,頭腦中大概會浮現出這樣的場景:每樣物品都有序地擺放在它應該在的地方,一目了然,并且一塵不染,非常干凈,令人愉快;同時,不那么明顯的,整潔往往暗示著沒有多余的東西,東西越少,越容易保持整潔。
整潔的代碼有同樣的特征:
1) 有序,各得其所,模塊的歸模塊,接口的歸接口,實現的歸實現。
處理對于人腦來說過于復雜的東西,自古以來有效的辦法就是分解,將大的分解成小的,使人腦在某一時刻只需要思考小的部分。要做到這點,除了分解,還需要保持模塊和模塊之間聯系盡可能少,只有這樣你才能專注思考眼前這一塊,而不必過于擔心它和其它模塊的相互影響。同樣,只有這樣,當軟件發生變動的時候,你才不至于陷入焦油坑。
相關術語:結構化、分層、抽象、解耦、正交、降低依賴、大量原則(SRP、OCP、LSP…)
2) 一目了然。
流暢,沒有障礙,它應該就是這個樣子,而不是別的樣子。任何維護工作的第一件事是什么?讀代碼。
相關術語:可讀、文字化編程(Kunth)、自解釋。
3) 一塵不染。
重點是保持。如果一直保持干凈,一旦出現污點,將會顯得非常刺眼,自然會被清除。相反,一扇窗戶破了,若無人關心,最終整條街道都會腐化。
相關術語:重構、溫水煮青蛙。
4) 只做必要的事,保持簡單。
從奧卡姆開始,到建筑,到飛機制造。“完成”不是指不能再往里塞東西,而是指不能再往外拿任何東西。
相關術語:KISS、敏捷。
5) 令人愉快。
成功永遠令人愉快,美永遠令人愉快。
相關術語:詩歌
4,其它
也許你已經發現了,如果保持代碼整潔,似乎就可以應對多種復雜度(但不是所有),這也是為什么好代碼除了可用,還需要整潔。
本文只是描述我心目中的好代碼,并不打算說明如何編寫好代碼,那需要太多的篇幅(和太多的爭議)。所以,至此為止。
瘋狂的孩子你慢一點,
把電話摘下然后消失一會兒,
對了,你可以放松一兩天,
你何時意識到……維也納在等著你?
——《陌生人》(The Stranger) Bill Joel
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。