上周六,公司進行了一次技術培訓,培訓的內容無外乎就是常見的一些重構,敏捷開發的觀點,當時因為有些事沒有去聽,但之後聽同事說了一些關於培訓內容的情況,也看了看培訓的大致講義,其實就是將重構等一些經典書籍的簡單匯總,談了些常識,原則性的東西。
那麼在這裡,我不是反對他的觀點,當然,我也沒有這樣的權利反對,只是語言是最容易產生誤會的,我只是糾正同樣一句話給人帶來的錯誤認識。
1. 代碼和注釋的關係
在培訓上,應該是說了這樣的話,好的代碼是不需要注釋的。
這裡我就談談我對注釋的看法。注釋的產生有三個目的:
A. 對方法名不能過長的妥協
B. 對閱讀者英文能力的妥協
C. 對複雜商務邏輯的標註
一般來說,為了可讀性和規矩,我們不會把方法名寫成一句完整的話,那麼就只能用一些簡單的詞彙來代替,這樣就出現,如果某個方法是一個相對複雜的商務邏輯方法時,你的方法名是沒有辦法完全準確地表達出整個方法的意思,這時,就只能依靠注釋了。所以我說,注釋首先是對方法名不能過長的妥協。
程式員水平參差不齊,尤其是英文水平,有的人過了GRE,有的人可能剛能勉勉強強讀懂初中單詞(在此無任何貶低他人的意思,我的英語就爛的出奇),因此為了提高工作效率,為了滿足大多數企業的需求,為了照顧當今國內的現狀,不能讓每個程式員都為了不認識的單詞去Google,因此我說,注釋是對閱讀者英文能力的妥協。
第三應該是注釋最大用場的地方,無論我們把方法的職責拆分得多細,都不可能避免在某一個方法裡面出現for,while,遞迴等複雜的商務邏輯或演算法,那麼當代碼需要被維護時,這段商務邏輯被人看懂也許是比較浪費時間的,因此最簡單的辦法就是添加註釋。
我說了很多注釋的存在價值,那麼注釋是不是一定存在,我是不是在對這個著名的軟體理論作挑戰呢?不是。
注釋應該是能少就少。不去寫不必要的注釋。當你對你的方法每一行都加註釋的時候,就說明你的方法本身是失敗的。
這就要求我們做到如下幾點:
A. 方法,類名,見名知義。
B. 不使用無意義的變數名,說個我們最簡單的,也是我們最常寫的代碼。
for(int i =0;i<arr.length;i++); i就是一個無意義的變數名,如果我們把i換成loop,是不是意義更明顯了呢。(補充說明:鑒於大家都在針對這句話來說,那我就改改吧,其實我只是想表達不要使用無意義的變數名,例子舉的不恰當,大家可以無視之。我只是想說明在程式會看到的某些變態的xxx,yyy,gddb之類的變數名字)
C. 把垃圾代碼消滅在萌芽。垃圾代碼必然導致恨多錯亂的邏輯,很可能這裡引入一個邏輯變數,那裡引入一個輔助參數,這樣的代碼,怎麼可能沒注釋呢。
最後總結下,注釋,需要有,記得以前看過一句話叫:完美的人生不需要解釋,完美的代碼不需要注釋。這個就有些太極端了,一個完美的代碼,又沒有注釋,那隻能說明這個項目的商務邏輯太簡單了。
2. 什麼是良好的軟體設計
完美的設計,不是不能增加,而是不能減少,這個是定義設計過度最恰當的一句話了,在我看來,補上一句:“並且不能修改”。這個是最恰當的,否則會被陷入無設計的錯覺當中。完整的一句話也就是:“完美的設計,不是不能增加,而是不能減少;不是不能擴充,而是不能修改。”
隨著越來越多的人說,設計模式(我說的是設計模式,而不是GOF的23種設計模式)是個沒有用的東西,我感覺特別無助。也許是從asp到asp.net這一代的轉換,很多人都習慣了在一個方法裡堆砌很多資料庫的操作。每次當修改一個Bug時,你做的是:首先找到這個按鈕,然後把方法從頭讀到尾,看到底哪句話出了問題。
如果對於一個小系統來說,這無可厚非,代碼邏輯簡單,隨便拿出一個程式員都可以做出這樣一整套的系統,最多是時間長短而已。可是這真的是開發一個軟體該有的方法嗎?
我們首先來說兩個原則:OCP(開閉原則)和 DRY(Don’t Repeat yourself)。如果你連這兩個原則都在否認,那麼好,你懷疑的是整個軟體史,連史上所有的軟體大師都不能說服你,我自然也無能為力了。
說最簡單的DRY確保了你封裝的必要性,而OCP則確保了你設計和分包的重要性。
很多人見到封裝就怕了,就總希望你把所有東西都寫到頁面上,一切邏輯都是一句最簡單的SQL,說封裝的東西看不懂,SQL是最容易懂的。那好,我來簡單地說下封裝。
封裝有兩個好處:
A. 你在外界可以重用被封裝好的方法,而無需關心內部的商務邏輯,這是方便使用者。職責分離不僅僅體現在軟體設計上,同樣應該體現在軟體工程,專案管理中,聞道有先後,術業有專攻,很少有人既是SQL專家又是CSS專家,同樣,很少有人既是技術專家又是業務專家。三層架構的劃分,其中很重要的一個目的就是職責分離。那麼說最簡單的,我把複雜的商務邏輯全都封裝到BLL裡,做使用者介面層的是不是就可以專註於介面的展示了呢?邏輯有了錯誤我來擔著,你只管按規則調用,那還怕什麼呢?
B. 封裝是安全的。封裝隱藏了一些對外不應公開的方法,使得外界無法訪問和調用,從而防止使用者因為誤操作而毀壞系統(或資料)。
再說個更實際的,我把方法封裝好,可以讓調用的方法更加精簡簡短,使得代碼看起來邏輯更清晰。如此這樣,你還討厭封裝嗎?
在接下來說分包和設計的問題,我們在這裡說OCP的原則是:對擴充開放,對修改關閉。那麼我們怎麼去最簡單地理解這句話呢?當我們要向原系統中增加需求時,無須變更原有代碼,無須更改原有代碼的dll,而只需要增加就可以了。設計模式發展到今天,終極目標已經是打造一個完全可配置的軟體項目,那麼這樣也就可以實現我們的完美OCP。
在你真的瞭解分層架構嗎?——寫給被PetShop"毒害"的朋友們 這篇文章中,T2噬菌體 指出了我們很多人對三層架構就是BLL+DAL+WebSite的誤解,其實當我們一步一步打造可配置的軟體項目時,當我們提出“面向組件編程“時,甚至說當我們提出“SOA”時,我們應該要想到,一個軟體應該是由無數個組件(.dll)來組成的,我們在設定檔中,針對這些組件進行自由選擇,每個.dll都應該是一個單獨的變化點,當我們在設計模式中,看到“每個類不應該超過一個使其變化的原因”時,我們應該想到,對於當今軟體來說,這個觀點應該改為:“每個DLL不應該存在超過一個使其變化的原因”。
我這樣說,您還會說,一個項目中存在很多.dll是個很恐怖的事情嗎?
3. 總結
迷迷糊糊寫了這麼多,我只是想說明,其實,每個程式員可以懷疑理論,但是首先,我們要看清楚這個軟體理論,吃透這個理論的本質內涵。
winter-cn 和我說過一句話,對我影響很大,“盡信書不如無書,可是當你盡疑書又何必有書”。有時我只是奉勸身邊的朋友,相信大多數的程式員還都是普通人,我們大多數還沒有達到國外那些軟體大師的水平,我們又憑什麼去懷疑人家幾十年的觀點,幾十年的軟體理論是錯誤的,是沒用的呢?
當你說RUP無用的時候,當你說設計模式無用的時候,當你說軟體工程流程沒用的時候,當你說分層沒用的時候,當你說某種軟體理論沒用的時候,當你說某個技術垃圾到不行的時候,先閉上眼睛,靜心想一想,和提出該理論的人比,我比他強嗎?
孤身和整個軟體學術界抗衡,你,還夠格嗎?