對幾個軟件開發傳統觀點的質疑和反駁
下面這些觀點都是程序員在教科書上、在編碼規范里、在正統的軟件工程流程里流傳開來的,幫助了許多人在程序員啟蒙期間養成了良好的習慣、原則。對許多人(包括曾經的我)來說,似乎是理所當然的。但是隨著閱歷的增長,視角在變化、看法也在變化,曾經的好惡現在都可能大翻身了。
為代碼寫足夠的注釋,讓代碼易于理解
“所有程序員都會寫自己看得懂的代碼,但只有優秀的程序員才寫大家看得懂的代碼。”這話沒錯,但是——
- 什么才是“大家看得懂”的定義?我有必要讓我的C++代碼對于一個月前才明白指針和引用區別的初學者簡單易懂么?
- 更重要的是,要代碼能夠“看得懂”,主要是靠足夠多的注釋嗎?
我覺得這兩點都是扯淡。
關于第1點,造就了一些自我感覺過度良好的人,習慣性地把前人寫的代碼批得體無完膚。在他們眼中,這段代碼巨爛,那段代碼是屎,更有甚者,在評審別人代碼的時候,一樣說出這樣的話來(請參見這篇文章里的“一坨屎型評審”)。
反對我的人會說,軟件公司做產品賺錢,它們希望你的代碼讓不熟悉項目的新員工快速閱讀、上手。這確實是個矛盾。說白了,你寫的代碼要和一個團隊的能力匹配。在一個魚龍混雜的團隊,甚至一個糟糕的團隊,你寫出的代碼也許很難和大伙兒產生共鳴,他們希望你寫最普通最易懂的代碼,沒有精巧的設計(我指的是,“某一些精巧的設計,恰恰是以降低代碼的可維護性為代價的”),沒有語言高級特性,看著只有順序、循環、分支判斷的基本代碼。如果大家都是JavaEE的初學者,那么就從JSP+Servlet開始吧,這樣你們才在一個圈子里,要不然,沒有人能真正和你一起討論設計和代碼的問題。
所以許多上進的程序員,會希望在一個牛人的團隊里工作。這就像足球運動員一樣,因為足球是集體運動,一個足球運動員能達到的高度,是和他所在的團隊息息相關的。在一個優秀的團隊里,大家個性各有千秋,擅長領域不甚相同,但是都學習迅速,能力不差太遠,大家閱讀代碼都能夠很快理解和領會,而且討論問題可以用一些程序員才明白的隱喻(比如有人說“我覺得這里應該用一個builder來實現”,大家都明白builder指的是什么),氛圍和效率顯而易見。
如果你恰好對當前需要用到的業務和技術特別熟悉,領先團隊里其他人一大截怎么辦?那你就該在做設計編碼的時候先行一步,你是那個最該去做架構設計、寫骨架代碼的人,完成一個架子以后再來給大家講解,并和大家討論,改進現有的設計。也就是說,你要多做一些更重要的事,而不是和大家一起分析、一起討論,甚至一人負責一個模塊,***的結果就是大家根本和你討論不到一塊兒去。
關于第2點,要代碼“看得懂”,是設計出來的,而不是注釋加出來的。這和產品質量一樣,產品質量是設計出來的,而不是測試測出來的。注釋的意義在于對當前代碼自解釋做不到的地方進行補充。
所以,你的代碼要易于理解,首先要保持簡潔和清晰,這既包括良好的設計,也包括良好的編碼習慣,也就是說,代碼是自解釋的,其次才通過注釋的補充,讓代碼更易懂。注意,我不是說注釋不重要和不必要,而是說,注釋應該完成它自己的功用,它遠不能代替代碼本身自我解釋的價值。
舉一個簡單的例子,你可以這樣寫代碼:
- /**
- * 圖表模型
- */
- class Chart{
- /**
- * 圖表長度
- */
- private int length;
- /**
- * 獲取圖表長度
- * @return 圖表長度
- */
- public int getLength(){
- return this.length;
- }
- /**
- * 設置圖表長度
- * @param length 圖表長度
- */
- public void setLength(int length){
- this.length = length;
- }
- }
好,那么你告訴我,這段代碼和下面這段代碼相比,你獲取了什么更多的有用信息?
- class Chart{
- private int length;
- public int getLength(){
- return this.length;
- }
- public void setLength(int length){
- this.length = length;
- }
- }
我想你懂我的意思,兩段代碼,代碼本身意思已經夠明確了,再加上這些無聊的注釋,只是浪費資源、浪費生命。很多編程語言,利用語法糖,連簡單 get、set方法都可以省了(比如Objective C),而加這種注釋的做法卻依然在反軟件、反人類而行。也許你和我一樣,曾經為了公司某些扯淡的規定,為了規避某些扯淡的代碼靜態檢查工具(比如 CheckStyle這樣的,甚至自己開發這種無聊的檢查工具)檢查結果中的警告信息,加上了(包括IDE自動生成)這些毫無意義的注釋,于是領導看了: “好,沒有警告信息,代碼質量好”。雖然至始都痛恨這樣的做法,但我還是做了,至今后悔。最讓人痛恨自己的事情就是不得不去做那些自己痛恨的事情。
設計文檔要詳細,細化到方法定義
持這個觀點的大有人在。對于這個觀點我并不是完全反對,如果你要說設計文檔需要“詳細到可以指導編碼”我還能同意,但是我確實非常不喜歡詳詳細細的設計文檔。肯定設計文檔的價值這沒有錯,但是過于詳細的設計文檔撰寫,往往容易造成紙上談兵的窘境。
有人說設計文檔太過粗略了做不好設計,事實上,文檔只是呈現設計的其中一種形式而已,做得好設計的人,可以一邊編碼一邊思考,可能輔助草稿紙上寫寫劃劃,就可以完成優秀的軟件;不會做設計的人,設計文檔寫多少頁都沒用。這讓我想起了今天和同事關于TDD的討論,會做設計的人,不讓他用TDD也能寫好代碼;不會做設計的人,TDD又有何用?所以讓TDD成為設計的主要工具,那就是扯淡。
再一個,在設計文檔中,不可能做完設計,不知你是否有這樣的體會,設計文檔思考得再縝密細致,等落到代碼上的時候,還會和開始的思考有許多不同,至少有很多細小的不同。這是因為設計思考本身就是貫穿整個設計編碼過程的,一人只做設計、另一人只寫代碼這樣的理想模式是不可能達成的。
我了解一些對日外包公司,程序員拿到手的設計文檔就是細化到方法定義了的,如果你有能力有志氣,在中國***就不要做外包,尤其是對日外包,這樣的公司拒絕你的一切思考,就是在摧殘人才。
另外一個原因,是針對一些闡明“設計文檔可以傳承業務和技術知識”觀點的人,詳細的設計文檔并不能夠傳承什么業務和技術,原因很簡單,詳細的文檔初始撰寫成本高,維護的成本更高。我不相信程序員在修改了代碼邏輯以后,會去經常保持設計文檔的同步性。這不合理,只有代碼才是保持***的,其它一切都會過時。而相對簡要或粗略的文檔,穩定性就要強得多。
讓項目組各個角色去評審代碼設計
下面我要駁斥的這個觀點來源于我的一些經歷,也許并不能算是主流觀點。
對于設計文檔的評審,如果是設計原理、實現原理,正到了程序員才關心的層面上,如果不寫代碼的測試跑來一起討論,這就成了浪費時間、制造矛盾的做法。我經歷過這樣的事情,覺得很幽默。專職測試人員的定位各有千秋,許多人經驗豐富、無可替代,但是至少,我接觸的測試人員中,他們幾乎是不閱讀代碼的,也就是說,對于代碼設計(注意,是代碼設計,不是產品設計)的討論,他們不該參與進來。
另外,不要說“我幾年前也是寫代碼的”,毛主席都講了,“不了解情況,就沒有發言權”,如果你對當前的代碼實現不了解,就不要來礙手礙腳地評審代碼層面的設計了。
我也經歷過這樣的場景,每一個產品都要組織一些有經驗的程序員,去給別的產品的代碼挑刺兒。我的看法是,這很難挑出特別有價值的毛病來,原因也是一樣的,你對別的產品業務不了解,那么要花大量精力去閱讀代碼,更要去熟悉業務,否則只能從代碼層面上摳摳細節。
所以,誰來把關實現層面的設計和代碼的質量最卓有成效呢?正是熟悉項目的程序員們,尤其是項目組骨干,或者一起參與設計、編碼和測試的架構師(其實架構師還是一名優秀的程序員,我從來不認為“只懂業務的架構師”有什么資格去做軟件架構)。
為代碼設置量化的限制指標
統計指標是有價值的,但是如果設置這些量化指標給程序員套限,則是違背客觀規律的行為。這一觀點我有必要舉例說明一下:
- 測試代碼覆蓋率不得低于95%(比如工具EMMA);
- 方法圈復雜度不能超過15(你也許知道圈復雜度的檢查工具SourceMonitor);
- 單個類的行數不能超過500,單個方法的行數不能超過200;
- 任意兩個類之間重復代碼行數不能超過10行(你可能知道重復代碼檢測工具Simian);
- ……
這些硬生生限制,都是反軟件、反人類的。你可以說圈復雜度高的方法也許過于復雜,你可以說重復比率高的代碼往往可以優化,但是這些都只是一個輔助的指標。這些工具都是用來幫助程序員改善他們的設計和代碼質量的,如今它們卻被用來做反程序員的事。
對于測試代碼覆蓋率的要求,而且有許許多多公司拿來作為代碼質量衡量的重要指標,我認為更是駭人聽聞。我寫代碼也做單元測試,但是會有選擇地寫UT 用例,不會去追求測試覆蓋率,而且測試再全面也不可能保證結果的絕對正確,好鋼要用在刀刃上,時間的投入要換取劃算的回報,而不是不計代價地補充測試用例。而且,在這里我要說的是,保證軟件質量的方式有很多,測試驗證的方式也有很多。即便覆蓋率達到100%,也不能說明質量高到哪兒去,追求覆蓋率始終太過功利。另外,有許多代碼本身就沒有多大被UT測試的價值,這也是不容忽視的。
優秀的程序員,應該難以容忍自己產出糟糕的代碼,也許對代碼有一點潔癖,對代碼之美有不懈的追求。對這樣的軟件的使用動機,也應該來源于程序員,而相關數據的采集,最終一定要為程序員服務。
今天只是把上面這些觀點做了個整理,在和別人談起這些的時候,其實我覺得我只是說了實話而已,我的觀點一點都不偏激。我知道很可能你會有不同看法,這太好不過了,但是善意地提醒你,請一定仔細思考一下,不要被公司的精神和文化洗了腦,我們都是程序員,我們最清楚,或許也都經歷過那些針對程序員、軟件開發荒唐可笑、乃至不可思議的做法。



























