Java代碼的編寫,對很多學過Java的朋友來說都是小菜一碟,對他們來說編寫Java代碼算不上是個很難的工作,但是能編寫出Java代碼,卻不代表他們所編寫的Java代碼有質量保障,高質量的Java代碼見證Java功底,你知道Java代碼質量該如何提高嗎?
很多人剛開始只求會編寫Java代碼,隨著編程經驗的增加,越來越追求Java代碼的質量,會Java編程沒什麼了不起的,但是能夠進行高質量的Java編程就相當不錯,也是企業十分渴求的Java人才,Java代碼質量在很大程度上影響著滿足需求的能力。
Java代碼質量如何提高?首先,高質量的Java代碼得具備可用性,這是最基本的,自然還得是不復雜的應用,編寫出來能夠為我們完成所期望工作的效果,不僅如此,還得在業務處理或者運行環境中,你的編程能夠承受相應壓力,具備相應的盯扮變更能力。
高質量的Java代碼還得具備足夠的安全性,能盡可能滿足客戶的需求,具有可維護性等等。北大凱毀灶青鳥認為高質量的Java代碼是一夜之間練不出來的,還是得堅持不斷練習才能夠一步一步取得進步,高質量的Java代碼你必須從日常就養成良好的編程習慣,比如注釋該有的得有。余基
很多初學者包括一些有經驗的程序員,在敲完代碼的最後一個字元後,馬上開始編譯和運行,迫不急待的想看到自己的工作成果。快速反饋有助於滿足自己的成就感,但是同時也會帶來一些問題:
讓編譯器幫你檢查語法錯誤可以省些時間,但程序員往往太專注這些錯誤了,以為改完這些錯誤就萬事大吉了。其實不然,很多錯誤編譯器是發現不了的,像內存錯誤和線程死鎖等等,這些錯誤可能逃過簡單的測試而遺留在代碼中,直到集成測試或者軟體發布之後才暴露出來,那時就要花更大代價去修改它們了。
修改完編譯錯誤之後就是運行程序了,運行起來有錯誤,就輪到調試器上場了。花了不少時間去調試,發現無非是些低級錯誤,或許你會自責自己粗心大意,但是下次可能還是犯同樣的錯誤。更嚴重的是這種debug&fix的方法,往往是頭痛醫頭腳痛醫腳,導致低質量的軟體。
讓編譯器幫你檢查語法錯誤,讓調試器幫你查BUG,這是天經地義的事,但這確實是又慢又爛的方法。就像你要到離家東邊1000米的地方開會,結果你往西邊走,又是坐車又是搭飛機,花了一周時間,也繞著地球轉了一周,終於到了會議室,你還大發感慨說,現代的交通工具真是發達啊。其實你往東走,走路也只要十多分鍾就到了。不管你的調試技巧有多高,都不如一次性寫好更高效。
下面是我在閱讀自己代碼時的一些方法:
檢查常見錯誤
第一遍閱讀時主要關注語法錯誤、代碼排版和命名規則等等問題,只要看不順眼就修改它們。讀完之後,你的代碼很少有低級錯誤,看起來也比較干凈清爽。第二遍游嘩重點關注常見編程錯誤,比如內存泄露和可能的越界訪問,變數沒有初始化,函數忘記返回值等等,在後面的章節中,我會介紹這些常見錯誤,避免這些錯誤可以為你省大量的時間。如果有時間,在測試完成之後,還可以考慮是否有更好的實現方法,甚至嘗試重新去實現它們。說了讀者可能不相信,在學習編程的前幾年,我經神知行常重寫整個模塊,只我覺得能做得更好,能驗證我的一些想法,或提高我的編程能力,即使連續幾天加班到晚上十一點,我也要重寫它們。
模擬計算機執行
常猛灶見錯誤是比較死的東西,按照檢查列表一條一條的做就行了。有些邏輯通常不是這么直觀的,這時可以自己模擬計算機去執行,假想你自己是計算機,讀入這些代碼時你會怎麼處理。北大青鳥認為這種方法能有效的完善我們的思路,考慮不同的輸入數據,各種邊界值,這能幫助我們想到一些沒有處理的情況,讓程序的邏輯更嚴謹。
③ 程序員需要關注哪些代碼優化質量問題
對於程序員來說,軟體編程開發代碼質量能夠直接敏前反應出一個程序員能力的高低,下面北大青鳥就一起來了解一下,在代碼質量優化方面,我們需要關賀閉注哪些問題。
1.吹毛求疵般地執行編碼規范
嚴格執行代碼編寫規范,可以使一個項目乃至一個公司的代碼具有完全統一的風格,就像同一個人編寫的一樣,而且命名良好的變數,函數,類和注釋,也無疑可以提高代碼的可讀性.具體落實到執行層面,可以參照Google的編碼規范或者java官方的編碼規范,網上可以找到,關鍵是要嚴格遵守,並且在codereview時,嚴格要求,沒有按照規范的一定要指出並且要求修改.
實際情況往往是雖然大家都知道優秀的代碼規范是怎樣的,但在具體寫代碼的過程中,卻執行的差強人意,很多情況是認識上橋拍清不夠重視,覺得一個變數或者函數的命名成哪樣關系不大,所以不夠推敲,注釋很多也都不寫,codereview的時候大家也都事不關己心態,或者覺得沒必要太摳細節,導致慢慢的整個codebase變得越來越差.所以這里還是要強調一下,細節決定成敗,提高團隊對代碼規范的認同及其嚴格的執行是關鍵.
2.編寫高質量的單元測試
單元測試是容易執行,且對提高代碼質量見效快的方法之一還。但還是有很多公司對單元測試重視不夠,包括一些大的互聯網公司,不寫或者隨便寫寫。
有些工程師覺得有測試團隊就夠了,再寫單元測試就是浪費時間。其實測試團隊的測試和單元測試是在不同層面上的,測試團隊的測試一般是黑盒測試,系統層面的集成測試,對於復雜系統來說,組合爆炸,測試團隊無法窮舉所有的測試用例。單元測試是代碼層面的測試,一般是針對類的測試。既然無法從系統的整體上保證100%符合我們的預期,那單元測試起碼能保證我們代碼在細粒度上運行符合預期。
有些工程師認為開發任務重沒時間寫。這個還是沒有足夠重視單元測試,覺得是可有可無的部分,才會有這樣的想法。寫好單元測試,節省很多解決線上bug的時間,開發時間反而更充足了。
還有很多工程師雖然在寫單元測試,但只對正常流程做測試。代碼中的bug多數是寫代碼時異常情況沒有考慮全面導致的,正常流程一般不會出問題。單元測試的作用就在於測試各種異常情況下代碼的運行是否符合預期,所以只對正常流程測試無法發揮單元測試真正的作用。
④ 對於程序員,提高軟體開發的質量和效率該從那些方面努力
1.提高代碼的規范性。編碼規范 可以提高代碼的可讀性,並且在代碼修改的時候很版容易。權
2.對功能進行分類,並拆分。分析出幾種處理邏輯。編寫代碼時,部分代碼可以。可以提編碼速度。
3.對功能進行分類,並合並。提出共通類。
4.不同的package對應不同的功能。
簡單的說,每天寫幾百行代碼。堅持半年或者1年,就知道什麼方式是適合你的了。 不寫代碼,光想,十年也還是那個水平。每個人的邏輯思維是不一樣的,寫代碼的方式也是不一樣的。有時間問,還不如多寫寫。或者,自己模擬現實個場景(或公司管理制度之類的),然後實現。寫幾個,很自然的就知道自己該怎麼寫了。
⑤ 如何編寫高質量的代碼
1. 打好基礎
寫出高質量代碼,並不是搭建空中樓閣,需要有一定的基礎,這里我重點強調與代碼質量密切相關的幾點:
掌握好開發語言,比如做Android就必須對Java足夠熟悉,《Effective Java》一書就是教授大家如何更好得掌握Java, 寫出高質量Java代碼。
熟悉開發平台, 不同的開發平台,有不同的API, 有不同的工作原理,同樣是Java代碼,在PC上寫與Android上寫很多地方不一樣,要去熟悉Android編程的一些特性,iOS編程的一些特性,了解清楚這些,才能寫出更加地道的代碼,充分發揮各自平台的優勢。
基礎的數據結構與演算法,掌握好這些在解決一些特定問題時,可以以更加優雅有效的方式處理。
基礎的設計原則,無需完全掌握23種經典設計模式,只需要了解一些常用的設計原則即可,甚至你也可以只了解什麼是低耦合,並在你的代碼中堅持實踐,也能寫出很不錯的代碼。
2. 代碼標准
代碼標准在團隊合作中尤為重要,誰也不希望一個項目中代碼風格各異,看得讓人糟心,即便是個人開發者,現在也需要跟各種開源項目打交道。標准怎麼定是一個老生常談的話題,我個人職業生涯中經歷過很多次的代碼標准討論會議,C++, C#, Java等等,大家有時會堅持自己的習慣不肯退讓。可現如今時代不一樣了,Google等大廠已經為我們制定好了各種標准,不用爭了,就用這些業界標准吧。
3. 想好再寫
除非你很清楚你要怎麼做,否則我不建議邊做邊想。
你真的搞清楚你要解決的問題是什麼了嗎?你的方案是否能有效?有沒有更優雅簡單的方案?准備怎麼設計它,必要的情況下,需要有設計文檔,復雜一些的設計需要有同行評審,寫代碼其實是很簡單的事情,前提是你得先想清楚。
4. 代碼重構
重構對於代碼質量的重要性不言而喻,反正我是很難一次把代碼寫得讓自己滿意、無可挑剔,《重構》這本書作為業內經典也理應人人必讀,也有其他類似的教授重構技巧的書,有些也非常不錯,遺憾的是我發現很多工作多年的同學甚至都沒有了解過重構的概念。
5. 技術債務
知乎上最近有個熱門問題《為什麼有些大公司技術弱爆了?》,其實裡面提到的很多歸根結底都是技術債務問題,這在一些大公司尤為常見。技術債務話題太大,但就代碼質量而言,我只想提一下不要因為這些債是前人留下的你就不去管,現實是沒有多少機會讓你從一個清爽清新的項目開始做起,你不得不去面對這些,你也沒法完全不跟這些所謂的爛代碼打交道。
因此我建議各位:當你負責一個小模塊時,除了把它做好之外,也要順便將與之糾纏在一起的技術債務還掉,因為這些債務最終將是整個團隊來共同承擔,任何一個人都別想獨善其身,如果你還對高質量代碼有追求的話。
作為團隊的技術負責人,也要頂住壓力,鼓勵大家勇於做出嘗試,引導大家不斷改進代碼質量,不要總是畏手畏腳,停滯不前,真要背鍋也得上,要有擔當。
6. 代碼審查
我曾經聽過一些較高級別的技術分享,竟然還不時聽到一些呼籲大家要做代碼審查的主題,我以為在這個級別的技術會議上,不應再討論代碼審查有什麼好,為什麼要做代碼審查之類的問題。同時我接觸過相當多所謂國內一線互聯網公司,竟有許多是不做代碼審查的,這一度讓我頗為意外。
這里也不想多談如何做好代碼審查,只是就代碼質量這點,不客氣地說:沒有過代碼審查經歷的同學,往往很難寫出高質量的代碼,尤其是在各種追求速度的糙快猛創業公司。
7. 靜態檢查
很多代碼上的問題,都可以通過一些工具來找到,某些場景下,它比人要靠譜得多,至少不會出現某些細節上的遺漏,同時也能有效幫助大家減少代碼審查的工作量。
Android開發中有Lint, Find bugs, PMD等優秀靜態檢查工具可用,通過改進這些工具找出的問題,就能對語法的細節,規范,編程的技巧有更多直觀了解。
建議最好與持續集成(CI),代碼審查環境配套使用, 每次提交的代碼都能自動驗證是否通過了工具的代碼檢查,通過才允許提交。
8. 單元測試
Android單元測試,一直備受爭議,主要還是原生的測試框架不夠方便,每跑一次用例需要在模擬器或者真機上運行,效率太低,也不方便在CI環境下自動構建單元測試,好在有Robolectric,能幫我們解決部分問題。
單元測試的一個非常顯著的優點是,當你需要修改大量代碼時,盡管放心修改,只需要保證單元測試用例通過即可,無需瞻前顧後。
9. 充分自測
有一種說法:程序員最害怕的是他自己寫的代碼,尤其是准備在眾人面前show自己的工作成果時,因此在寫完代碼後,需要至少跑一遍基本的場景,一些簡單的異常流。在把你的工作成果提交給測試或用戶前,充分自測是基本的職業素養,不要總想著讓測試幫你找問題,隨便用幾下就Crash的東西,你好意思拿給別人嗎?
10. 善用開源
並非開源的東西,質量就高,但至少關注度較高,使用人數較多,口碑較好的開源項目,質量是有一定保證的,這其中的道理很簡單。即便存在一些問題,也可以通過提交反饋,不斷改進。最重要的是,你自己花時間造的輪子,需要很多精力維護,而充分利用開源項目,能幫助你節省很多時間,把精力專注在最需要你關心的問題上。
⑥ 如何編寫高質量的代碼!
載選<編程思想>
非程序員 編 著
代碼永遠會有BUG,在這方面沒有最好只有更好。高效是程序員必須作到的事情,無錯是程序員一生的追求。復用、分而治之、折衷是代碼哲學的基本思想。模塊化與面向對象是實現高效無錯代碼的方法。高效無錯代碼需要思想與實踐的不斷反復。
1.2.1 命名約定
命令規范基本上採用了微軟推薦的匈牙利命名法,略有簡化。
1. 常量
常量由大寫字母和數字組成,中間可以下劃線分隔,如 CPU_8051。
2. 變數
變數由小寫(變數類型)字母開頭,中間以大寫字母分隔,可以添加變數域前綴(變數活動域前綴以下劃線分隔)。如: v_nAcVolMin(交流電壓最小值)。
變數域前綴見下表
局部變數,如果變數名的含義十分明顯,則不加前綴,避免煩瑣。如用於循環的int型變數 i,j,k ;float 型的三維坐標(x,y,z)等。
3. 函數名一般由大寫字母開頭,中間以大寫字母分隔,如SetSystemPara。函數命名採用動賓形式。如果函數為最底層,可以考慮用全部小寫,單詞間採用帶下劃線的形式。如底層圖形函數:pixel、lineto以及讀鍵盤函數get_key 等。
4. 符號名應該通用或者有具體含義,可讀性強。尤其是全局變數,靜態變數含義必須清晰。C++中的一些關鍵詞不能作為符號名使用,如class、new、friend等。符號名長度小於31個,與ANSI C 保持一致。命名只能用26個字母,10個數字,以及下劃線『_』來組成,不要使用『$』『@』等符號。下劃線『_』使用應該醒目,不能出現在符號的頭尾,只能出現在符號中間,且不要連續出現兩個。
5. 程序中少出現無意義的數字,常量盡量用宏替代。
1.2.2 使用斷言
程序一般分為Debug版本和Release版本,Debug版本用於內部調試,Release版本發行給用戶使用。
斷言assert是僅在Debug版本起作用的宏,它用於檢查「不應該」發生的情況。以下是一個內存復製程序,在運行過程中,如果assert的參數為假,那麼程序就會中止(一般地還會出現提示對話,說明在什麼地方引發了assert)。
//復制不重疊的內存塊
void memcpy(void *pvTo, void *pvFrom, size_t size)
{
void *pbTo = (byte *) pvTo;
void *pbFrom = (byte *) pvFrom;
assert( pvTo != NULL && pvFrom != NULL );
while(size - - > 0 )
*pbTo + + = *pbFrom + + ;
return (pvTo);
}
assert不是一個倉促拼湊起來的宏,為了不在程序的Debug版本和Release版本引起差別,assert不應該產生任何副作用。所以assert不是函數,而是宏。程序員可以把assert看成一個在任何系統狀態下都可以安全使用的無害測試手段。
以下是使用斷言的幾個原則:
1)使用斷言捕捉不應該發生的非法情況。不要混淆非法情況與錯誤情況之間的區別,後者是必然存在的並且是一定要作出處理的。
2)使用斷言對函數的參數進行確認。
3)在編寫函數時,要進行反復的考查,並且自問:「我打算做哪些假定?」一旦確定了的假定,就要使用斷言對假定進行檢查。
4)一般教科書都鼓勵程序員們進行防錯性的程序設計,但要記住這種編程風格會隱瞞錯誤。當進行防錯性編程時,如果「不可能發生」的事情的確發生了,則要使用斷言進行報警。
1.2.3 優化/效率
規則一:對於在中斷函數/線程和外部函數中均使用的全局變數應用volatile定義。例如:
volatile int ticks;
void timer(void) interrupt 1 //中斷處理函數
{
ticks++
}
void wait(int interval)
{
tick=0;
while(tick<interval);
}
如果未用volatile,由於while循環是一個空循環,編譯器優化後(編譯器並不知道此變數在中斷中使用)將會把循環優化為空操作!這就顯然不對了。
規則二:不要編寫一條過分復雜的語句,緊湊的C++/C代碼並不見到能得到高效率的機器代碼,卻會降低程序的可理解性,程序出錯誤的幾率也會提高。
規則三:變數類型編程中應用原則:盡量採用小的類型(如果能夠不用「Float」就盡量不要去用)以及無符號Unsigned類型,因為符號運算耗費時間較長;同時函數返回值也盡量採用Unsigned類型,由此帶來另外一個好處:避免不同類型數據比較運算帶來的隱性錯誤。
1.2.4 其他
規則一:不要編寫集多種功能於一身的函數,在函數的返回值中,不要將正常值和錯誤標志混在一起。
規則二:不要將BOOL值TRUE和FALSE對應於1和0進行編程。大多數編程語言將FALSE定義為0,任何非0值都是TRUE。Visual C++將TRUE定義為1,而Visual Basic則將TRUE定義為-1。例如:
BOOL flag;
…
if(flag) { // do something } // 正確的用法
if(flag==TRUE) { // do something } // 危險的用法
if(flag==1) { // do something } // 危險的用法
if(!flag) { // do something } // 正確的用法
if(flag==FALSE) { // do something } // 不合理的用法
if(flag==0) { // do something } // 不合理的用法
規則三:小心不要將「= =」寫成「=」,編譯器不會自動發現這種錯誤。
規則四:建議統一函數返回值為無符號整形,0代表無錯誤,其他代表錯誤類型。
1.3 模塊化的C編程
C語言雖然不具備C++的面向對象的成分,但仍應該吸收面向對象的思想,採用模塊化編程思路。面向對象的思想與面向對象的語言是兩個概念。非面向對象的語言依然可以完成面向對象的編程,想想C++的誕生吧!
C++沒有理由對C存在傲慢與偏見,不是任何場合C++方法都是解決問題的良葯,譬如面對嵌入式系統效率和空間的雙重需求。注意我們談的是方法,而不是指編譯器。
C在軟體開發上存在的首要問題是缺乏對數據存取的控制(封裝),C編程者樂而不疲的使用著大量extern形式的全局變數在各模塊間交換著數據,「多方便啊」編程者樂曰,並傳授給下一個編程者。這樣多個變數出現在多個模塊中,剪不斷理還亂,直到有一天終於發現找一個「人」好難。一個東西好吃,智者淺嘗之改進之,而愚者只會直至撐死。
這世上本沒有什麼救世主,應在C上多下功夫,程序員和C締造者早就有過思考,相信野百合也有春天,還是看看C語言如何實現模塊化編程方法,在部分程度上具備了OO特性封裝與多態。
在具體闡述之前,需要明確生存期與可見性的概念。生存期指的是變數在內存的生存周期,可見性指的是變數在當前位置是否可用。兩者有緊密聯系,但不能混為一談。一個人存在但不可見只能解釋成上帝或靈魂,一個變數存在但不可見卻並非咄咄怪事,模塊化方法正是利用了靜態函數、靜態變數這些「精靈」們特殊的生存期與可見性。
最後需要明確一點的是這里的模塊是以一個.C文件為單位。
規則一:利用函數命名規則和靜態函數
模塊中不被其他模塊調用的內部函數採用以下命名規則:用全部小寫,單詞間採用帶下劃線的形式。如底層圖形函數:pixel、lineto以及讀鍵盤函數get_key等。這些函數應定義為static靜態函數,這樣在其他模塊錯誤地調用這些函數時編譯器能給出錯誤(如BC編譯器)。(注意:有些編譯器不能報告錯誤,但為了代碼風格一致和函數層次清晰,仍建議這樣作)。
規則二:利用靜態變數
模塊中不能被其他模塊讀寫的全局變數應採用static聲明,這樣在其他模塊錯誤地讀寫這些變數時編譯器能給出警告(C51編譯器)或錯誤(BC編譯器)。
規則三:引入OO介面概念和指針傳參
模塊間的數據介面(也就是函數)應該事先較充分考慮,需要哪些介面,通過介面需要操作哪些數據,盡量作到介面的不變性。
模塊間地數據交換盡量通過介面完成,方法是通過函數傳參數,為了保證程序高效和減少堆棧空間,傳大量參數(如結構)應採用傳址的方式,通過指針作為函數參數或函數返回指針,盡量杜絕extern形式的全局變數,請注意是extern形式的全局變數,模塊內部的全局變數是允許和必須的。
傳指針參數增加的開銷主要是作參數的指針和局部指針的數據空間(嵌入式系統(如C51)往往由於堆棧空間有限,函數參數會放到外部RAM的堆棧中),增加的代碼開銷僅是函數的調用,帶來的是良好的模塊化結構,而且使用介面函數會比在代碼中多處直接使用全局變數大大節約代碼空間。
需注意一點的事物總有他的兩面性,水能載舟,也能覆舟。對於需要頻繁訪問的變數如果仍採用介面傳遞,函數調用的開銷是巨大的,這時應考慮仍採用extern全局變數。
以下演示了兩個C模塊交換數據:
//Mole1.C
OneStruct* void GetOneStruct(void); //獲取模塊1數據介面
void SetOneStruct(OneStruct* pOneStruct); //寫模塊1數據介面
struct OneStruct
{
int m¬_imember;
//……
}t1; //模塊1的數據
//t1初始化代碼…..
OneStruct* void GetOneStruct(void)
{
OneStruct* pt1; //只需定義一個局部變數
t1.imember=15;
pt1=&t1;
return pt1;
}
void SetOneStruct(OneStruct* pOneStruct)
{
t1.imember=pOneStruct->imember;
//…….
}
//Mole2.C
void OperateOneStruct(void); //模塊2通過模塊1提供的介面操作模塊1的數據
OneStruct* void GetOneStruct(void);
void SetOneStruct(OneStruct* pOneStruct);
void OperateOneStruct(void)
{
OneStruct* pt2; //只需定義一個局部變數
pt2=GetOneStruct(); //讀取數據
SetOneStruct(pt2); //改寫數據
}
採用介面訪問數據可以避免一些錯誤,因為函數返回值只能作右值,全局變數則不然。
例如 cOneChar == 4; 可能被誤為cOneChar = 4;
規則四:有限的封裝與多態
不要忘記C++的class源於C的struct,C++的虛函數機制實質是函數指針。為了使數據、方法能夠封裝在一起,提高代碼的重用度,如對於一些與硬體相關的數據結構,建議採用在數據結構中將訪問該數據結構的函數定義為結構內部的函數指針。這樣當硬體變化,需要重寫訪問該硬體的函數,只要將重寫的函數地址賦給該函數指針,高層代碼由於使用的是函數指針,所以完全不用動,實現代碼重用。而且該函數指針可以通過傳參數或全局變數的方式傳給高層代碼,比較方便。例如:
struct OneStruct
{
int m¬_imember;
int (*func)(int,int);
//……
}t2;
⑦ 如何提高團隊代碼質量
一、最根本也是第一步要做的就是,在設計系統架構階段就需要充分地考慮系統的可擴展性、模塊的高聚合性以及介面靈活易用的性。要做到這一點,就和對需求的分析、系統的了解和經驗有很大關系了,需要長期的積累和經常對架構的思考與實踐。交給團隊裡面最牛逼的一個人去主導,比較牛逼的幾人參與討論來做這一步吧。
二、選用一個適合需求的開發框架,會讓你事倍功半。PHP的框架有很多,各自有各自的特性和優劣,可以比較選擇。Python的tornado在做Web應用的時候比較方便。同樣前段也需要代碼框架的支持,Javascript中jQuery能勝任大多數項目,HTML和CSS可以嘗試使用Twitter的Bootstrap。使用框架對代碼的健壯性有幫助嗎?當然有!因為框架封裝實現很多常用的功能,這樣我們自己的代碼量會大大減少。直觀一點講,代碼量少了,bug自然就少了。其實最重要的是代碼量少了,程序的邏輯和結構會更加清晰,從而減少Bug的出現。
三、多人協作需要良好的代碼管理工具。SVN可以考慮淘汰了,用分布式的GIT。
四、團隊還需要統一的開發環境。包括統一的編碼規范、統一的語言版本、統一的編輯器配置(tab和空格之類)、統一的文件編碼,統一的資料庫等等。這樣可以完全避免因為環境不同而導致的Bug。
五、較優秀的程序員應該負責較初級的程序員的代碼質量,定期對初級程序員的代碼進行review。同時團隊內部應該有針對性對一些比較復雜或者變態的部分進行code review。
六、對於系統的破窗和腫瘤,要適時適量地清除,絕對不能放任不管。
⑧ 一堂如何提高代碼質量的培訓課
今天這堂培訓課講什麼呢?我既不講Spring,也不講Hibernate,更不講Ext,我不講任何一個具體的技術。我們拋開任何具體的技術,來談談如何提高代碼質量。如何提高代碼質量,相信不僅是在座所有人苦惱的事情,也是所有軟體項目苦惱的事情。如何提高代碼質量呢,我認為我們首先要理解什麼是高質量的代碼。 高質液搏量代碼的三要素 我們評價高質量代碼有三要素:可讀性、可維護性、可變更性。我們的代碼要一個都不能少地達到了這三要素的要求才能算高質量的代碼。 1. 可讀性強 一提到可讀性似乎有一些老生常談的味道,但令人沮喪的是,雖然大家一而再,再而三地強調可讀性,但我們的代碼在可讀性方面依然做得非常糟糕。由於工作的需要,我常常需要去閱讀他人的代碼,維護他人設計的模塊。每當我看到大段大段、密密麻麻的代碼,而且還沒有任何的注釋時常常感慨不已,深深體會到了這項工作的重要。由於分孝埋唯工的需要,我們寫的代碼難免需要別人去閱讀和維護的。而對於許多程序員來說,他們很少去閱讀和維巧培護別人的代碼。正因為如此,他們很少關注代碼的可讀性,也對如何提高代碼的可讀性缺乏切身體會。有時即使為代碼編寫了注釋,也常常是注釋語言晦澀難懂形同天書,令閱讀者反復斟酌依然不明其意。針對以上問題,我給大家以下建議: 1)不要編寫大段的代碼 如果你有閱讀他人代碼的經驗,當你看到別人寫的大段大段的代碼,而且還不怎麼帶注釋,你是怎樣的感覺,是不是「嗡」地一聲頭大。各種各樣的功能糾纏在一個方法中,各種變數來回調用,相信任何人多不會認為它是高質量的代碼,但卻頻繁地出現在我們編寫的程序了。如果現在你再回顧自己寫過的代碼,你會發現,稍微編寫一個復雜的功能,幾百行的代碼就出去了。一些比較好的辦法就是分段。將大段的代碼經過整理,分為功能相對獨立的一段又一段,並且在每段的前端編寫一段注釋。這樣的編寫,比前面那些雜亂無章的大段代碼確實進步了不少,但它們在功能獨立性、可復用性、可維護性方面依然不盡人意。從另一個比較專業的評價標准來說,它沒有實現低耦合、高內聚。我給大家的建議是,將這些相對獨立的段落另外封裝成一個又一個的函數。 許多大師在自己的經典書籍中,都鼓勵我們在編寫代碼的過程中應當養成不斷重構的習慣。我們在編寫代碼的過程中常常要編寫一些復雜的功能,起初是寫在一個類的一個函數中。隨著功能的逐漸展開,我們開始對復雜功能進行歸納整理,整理出了一個又一個的獨立功能。這些獨立功能有它與其它功能相互交流的輸入輸出數據。當我們分析到此處時,我們會非常自然地要將這些功能從原函數中分離出來,形成一個又一個獨立的函數,供原函數調用。在編寫這些函數時,我們應當仔細思考一下,為它們取一個釋義名稱,並為它們編寫注釋(後面還將詳細討論這個問題)。另一個需要思考的問題是,這些函數應當放到什麼地方。這些函數可能放在原類中,也可能放到其它相應職責的類中,其遵循的原則應當是「職責驅動設計」(後面也將詳細描述)。 下面是我編寫的一個從XML文件中讀取數據,將其生成工廠的一個類。這個類最主要的一段程序就是初始化工廠,該功能歸納起來就是三部分功能:用各種方式嘗試讀取文件、以DOM的方式解析XML數據流、生成工廠。而這些功能被我歸納整理後封裝在一個不同的函數中,並且為其取了釋義名稱和編寫了注釋: Java代碼/** * 初始化工廠。根據路徑讀取XML文件,將XML文件中的數據裝載到工廠中 * @param path XML的路徑 */publicvoid initFactory(String path){ if(findOnlyOneFileByClassPath(path)){return;} if(findResourcesByUrl(path)){return;} if(findResourcesByFile(path)){return;} this.paths = new String[]{path}; } /** * 初始化工廠。根據路徑列表依次讀取XML文件,將XML文件中的數據裝載到工廠中 * @param paths 路徑列表 */publicvoid initFactory(String[] paths){ for(int i=0; i>Java>>Code Style>>Code Templates>>Comments」中,可以簡單的修改一下。 「Files」代表的是我們每新建一個文件(可能是類也可能是介面)時編寫的注釋,我通常設定為: Java代碼/* * created on ${date} */ 「Types」代表的是我們新建的介面或類前的注釋,我通常設定為: Java代碼/** * * @author ${user} */ 第一行為一個空行,是用於你寫該類的注釋。如果你採用「職責驅動設計」,這里首先應當描述的是該類的職責。如果需要,你可以寫該類一些重要的方法及其用法、該類的屬性及其中文含義等。 ${user}代表的是你在windows中登陸的用戶名。如果這個用戶名不是你的名稱,你可以直接寫死為你自己的名稱。 其它我通常都保持為默認值。通過以上設定,你在創建類或介面的時候,系統將自動為你編寫好注釋,然後你可以在這個基礎上進行修改,大大提高注釋編寫的效率。 同時,如果你在代碼中新增了一個函數時,通過Alt+Shift+J快捷鍵,可以按照模板快速添加註釋。 在編寫代碼時如果你編寫的是一個介面或抽象類,我還建議你在@author後面增加@see注釋,將該介面或抽象類的所有實現類列出來,因為閱讀者在閱讀的時候,尋找介面或抽象類的實現類比較困難。 Java代碼/** * 抽象的單表數組查詢實現類,僅用於單表查詢 * @author 范鋼* @see com.htxx.support.query.DefaultArrayQuery * @see com.htxx.support.query.DwrQuery */publicabstractclass ArrayQuery implements ISingleQuery { ... 2. 可維護性 軟體的可維護性有幾層意思,首先的意思就是能夠適應軟體在部署和使用中的各種情況。從這個角度上來說,它對我們的軟體提出的要求就是不能將代碼寫死。 1)代碼不能寫死 我曾經見我的同事將系統要讀取的一個日誌文件指定在C盤的一個固定目錄下,如果系統部署時沒有這個目錄以及這個文件就會出錯。如果他將這個決定路徑下的目錄改為相對路徑,或者通過一個屬性文件可以修改,代碼豈不就寫活了。一般來說,我在設計中需要使用日誌文件、屬性文件、配置文件,通常都是以下幾個方式:將文件放到與類相同的目錄,使用ClassLoader.getResource()來讀取;將文件放到classpath目錄下,用File的相對路徑來讀取;使用web.xml或另一個屬性文件來制定讀取路徑。 我也曾見另一家公司的軟體要求,在部署的時候必須在C:/bea目錄下,如果換成其它目錄則不能正常運行。這樣的設定常常為軟體部署時帶來許多的麻煩。如果伺服器在該目錄下已經沒有多餘空間,或者已經有其它軟體,將是很撓頭的事情。 2)預測可能發生的變化 除此之外,在設計的時候,如果將一些關鍵參數放到配置文件中,可以為軟體部署和使用帶來更多的靈活性。要做到這一點,要求我們在軟體設計時,應當有更多的意識,考慮到軟體應用中可能發生的變化。比如,有一次我在設計財務軟體的時候,考慮到一些單據在製作時的前置條件,在不同企業使用的時候,可能要求不一樣,有些企業可能要求嚴格些而有些要求鬆散些。考慮到這種可能的變化,我將前置條件設計為可配置的,就可能方便部署人員在實際部署中進行靈活變化。然而這樣的配置,必要的注釋說明是非常必要的。 軟體可維護性的另一層意思就是軟體的設計便於日後的變更。這一層意思與軟體的可變更性是重合的。所有的軟體設計理論的發展,都是從軟體的可變更性這一要求逐漸展開的,它成為了軟體設計理論的核心。 3. 可變更性 前面我提到了,軟體的變更性是所有軟體理論的核心,那麼什麼是軟體的可變更性呢?按照現在的軟體理論,客戶對軟體的需求時時刻刻在發生著變化。當軟體設計好以後,為應對客戶需求的變更而進行的代碼修改,其所需要付出的代價,就是軟體設計的可變更性。由於軟體合理的設計,修改所付出的代價越小,則軟體的可變更性越好,即代碼設計的質量越高。一種非常理想的狀態是,無論客戶需求怎樣變化,軟體只需進行適當的修改就能夠適應。但這之所以稱之為理想狀態,因為客戶需求變化是有大有小的。如果客戶需求變化非常大,即使再好的設計也無法應付,甚至重新開發。然而,客戶需求的適當變化,一個合理的設計可以使得變更代價最小化,延續我們設計的軟體的生命力。 1)通過提高代碼復用提高可維護性 我曾經遇到過這樣一件事,我要維護的一個系統因為應用范圍的擴大,它對機關級次的計算方式需要改變一種策略。如果這個項目統一採用一段公用方法來計算機關級次,這樣一個修改實在太簡單了,就是修改這個公用方法即可。但是,事實卻不一樣,對機關級次計算的代碼遍布整個項目,甚至有些還寫入到了那些復雜的SQL語句中。在這樣一種情況下,這樣一個需求的修改無異於需要遍歷這個項目代碼。這樣一個實例顯示了一個項目代碼復用的重要,然而不幸的是,代碼無法很好復用的情況遍布我們所有的項目。代碼復用的道理十分簡單,但要具體運作起來非常復雜,它除了需要很好的代碼規劃,還需要持續地代碼重構。 對整個系統的整體分析與合理規劃可以根本地保證代碼復用。系統分析師通過用例模型、領域模型、分析模型的一步一步分析,最後通過正向工程,生成系統需要設計的各種類及其各自的屬性和方法。採用這種方法,功能被合理地劃分到這個類中,可以很好地保證代碼復用。 採用以上方法雖然好,但技術難度較高,需要有高深的系統分析師,並不是所有項目都能普遍採用的,特別是時間比較緊張的項目。通過開發人員在設計過程中的重構,也許更加實用。當某個開發人員在開發一段代碼時,發現該功能與前面已經開發功能相同,或者部分相同。這時,這個開發人員可以對前面已經開發的功能進行重構,將可以通用的代碼提取出來,進行相應的改造,使其具有一定的通用性,便於各個地方可以使用。 一些比較成功的項目組會指定一個專門管理通用代碼的人,負責收集和整理項目組中各個成員編寫的、可以通用的代碼。這個負責人同時也應當具有一定的代碼編寫功力,因為將專用代碼提升為通用代碼,或者以前使用該通用代碼的某個功能,由於業務變更,而對這個通用代碼的變更要求,都對這個負責人提出了很高的能力要求。 雖然後一種方式非常實用,但是它有些亡羊補牢的味道,不能從整體上對項目代碼進行有效規劃。正因為兩種方法各有利弊,因此在項目中應當配合使用。 2)利用設計模式提高可變更性 對於初學者,軟體設計理論常常感覺晦澀難懂。一個快速提高軟體質量的捷徑就是利用設計模式。這里說的設計模式,不僅僅指經典的32個模式,是一切前人總結的,我們可以利用的、更加廣泛的設計模式。 a. if...else... 這個我也不知道叫什麼名字,最早是哪位大師總結的,它出現在Larman的《UML與模式應用》,也出現在出現在Mardin的《敏捷軟體開發》。它是這樣描述的:當你發現你必須要設計這樣的代碼:「if...elseif...elseif...else...」時,你應當想到你的代碼應當重構一下了。我們先看看這樣的代碼有怎樣的特點。 Java代碼if(var.equals("A")){ doA(); } elseif(var.equals("B")){ doB(); } elseif(var.equals("C")){ doC(); } else{ doD(); } 這樣的代碼很常見,也非常平常,我們大家都寫過。但正是這樣平常才隱藏著我們永遠沒有注意的問題。問題就在於,如果某一天這個選項不再僅僅是A、B、C,而是增加了新的選項,會怎樣呢?你也許會說,那沒有關系,我把代碼改改就行。然而事實上並非如此,在大型軟體研發與維護中有一個原則,每次的變更盡量不要去修改原有的代碼。如果我們重構一下,能保證不修改原有代碼,僅僅增加新的代碼就能應付選項的增加,這就增加了這段代碼的可維護性和可變更性,提高了代碼質量。那麼,我們應當如何去做呢? 經過深入分析你會發現,這里存在一個對應關系,即A對應doA(),B對應doB()...如果將doA()、doB()、doC()...與原有代碼解耦,問題就解決了。如何解耦呢?設計一個介面X以及它的實現A、B、C...每個類都包含一個方法doX(),並且將doA()的代碼放到A.doX()中,將doB()的代碼放到B.doX()中...經過以上的重構,代碼還是這些代碼,效果卻完全不一樣了。我們只需要這樣寫: Java代碼X x = factory.getBean(var); x.doX(); 這樣就可以實現以上的功能了。我們看到這里有一個工廠,放著所有的A、B、C...並且與它們的key對應起來,並且寫在配置文件中。如果出現新的選項時,通過修改配置文件就可以無限制的增加下去。 這個模式雖然有效提高了代碼質量,但是不能濫用,並非只要出現if...else...就需要使用。由於它使用了工廠,一定程度上增加了代碼復雜度,因此僅僅在選項較多,並且增加選項的可能性很大的情況下才可以使用。另外,要使用這個模式,繼承我在附件中提供的抽象類XmlBuildFactoryFacade就可以快速建立一個工廠。如果你的項目放在spring或其它可配置框架中,也可以快速建立工廠。設計一個Map靜態屬性並使其V為這些A、B、C...這個工廠就建立起來了。 b. 策略模式 也許你看過策略模式(strategy model)的相關資料但沒有留下太多的印象。一個簡單的例子可以讓你快速理解它。如果一個員工系統中,員工被分為臨時工和正式工並且在不同的地方相應的行為不一樣。在設計它們的時候,你肯定設計一個抽象的員工類,並且設計兩個繼承類:臨時工和正式工。這樣,通過下溯類型,可以在不同的地方表現出臨時工和正式工的各自行為。在另一個系統中,員工被分為了銷售人員、技術人員、管理人員並且也在不同的地方相應的行為不一樣。同樣,我們在設計時也是設計一個抽象的員工類,並且設計數個繼承類:銷售人員、技術人員、管理人員。現在,我們要把這兩個系統合並起來,也就是說,在新的系統中,員工既被分為臨時工和正式工,又被分為了銷售人員、技術人員、管理人員,這時候如何設計。如果我們還是使用以往的設計,我們將不得不設計很多繼承類:銷售臨時工、銷售正式工、技術臨時工、技術正式工。。。如此的設計,在隨著劃分的類型,以及每種類型的選項的增多,呈笛卡爾增長。通過以上一個系統的設計,我們不得不發現,我們以往學習的關於繼承的設計遇到了挑戰。 解決繼承出現的問題,有一個最好的辦法,就是採用策略模式。在這個應用中,員工之所以要分為臨時工和正式工,無非是因為它們的一些行為不一樣,比如,發工資時的計算方式不同。如果我們在設計時不將員工類分為臨時工類和正式工類,而僅僅只有員工類,只是在類中增加「工資發放策略」。當我們創建員工對象時,根據員工的類型,將「工資發放策略」設定為「臨時工策略」或「正式工策略」,在計算工資時,只需要調用策略類中的「計算工資」方法,其行為的表現,也設計臨時工類和正式工類是一樣的。同樣的設計可以放到銷售人員策略、技術人員策略、管理人員策略中。一個通常的設計是,我們將某一個影響更大的、或者選項更少的屬性設計成繼承類,而將其它屬性設計成策略類,就可以很好的解決以上問題。 使用策略模式,你同樣把代碼寫活了,因為你可以無限制地增加策略。但是,使用策略模式你同樣需要設計一個工廠——策略工廠。以上實例中,你需要設計一個發放工資策略工廠,並且在工廠中將「臨時工」與「臨時工策略」對應起來,將「正式工」與「正式工策略」對應起來。 c. 適配器模式 我的筆記本是港貨,它的插頭與我們常用的插座不一樣,所有我出差的時候我必須帶一個適配器,才能使用不同地方的插座。這是一個對適配器模式最經典的描述。當我們設計的系統要與其它系統交互,或者我們設計的模塊要與其它模塊交互時,這種交互可能是調用一個介面,或者交換一段數據,接受方常常因發送方對協議的變更而頻繁變更。這種變更,可能是接受方來源的變更,比如原來是A系統,現在變成B系統了;也可能是接受方自身的代碼變更,如原來的介面現在增加了一個參數。由於發送方的變更常常導致接受方代碼的不穩定,即頻繁跟著修改,為接受方的維護帶來困難。 遇到這樣的問題,一個有經驗的程序員馬上想到的就是採用適配器模式。在設計時,我方的介面按照某個協議編寫,並且保持固定不變。然後,在與真正對方介面時,在前段設計一個適配器類,一旦對方協議發生變更,我可以換個適配器,將新協議轉換成原協議,問題就解決了。適配器模式應當包含一個介面和它的實現類。介面應當包含一個本系統要調用的方法,而它的實現類分別是與A系統介面的適配器、與B系統介面的適配器... 我曾經在一個項目中需要與另一個系統介面,起初那個系統通過一個數據集的方式為我提供數據,我寫了一個接收數據集的適配器;後來改為用一個XML數據流的形式,我又寫了一個接收XML的適配器。雖然為我提供數據的方式不同,但是經過適配器轉換後,輸出的數據是一樣的。通過在spring中的配置,我可以靈活地切換到底是使用哪個適配器。 d. 模板模式 32個經典模式中的模板模式,對開發者的代碼規劃能力提出了更高的要求,它要求開發者對自己開發的所有代碼有一個相互聯系和從中抽象的能力,從各個不同的模塊和各個不同的功能中,抽象出其過程比較一致的通用流程,最終形成模板。譬如說,讀取XML並形成工廠,是許多模塊常常要使用的功能。它們雖然有各自的不同,但是總體流程都是一樣的:讀取XML文件、解析XML數據流、形成工廠。正因為有這樣的特徵,它們可以使用共同的模板,那麼,什麼是模板模式呢? 模板模式(Template Model)通常有一個抽象類。在這個抽象類中,通常有一個主函數,按照一定地順序去調用其它函數。而其它函數往往是某這個連續過程中的各個步驟,如以上實例中的讀取XML文件、解析XML數據流、形成工廠等步驟。由於這是一個抽象類,這些步驟函數可以是抽象函數。抽象類僅僅定義了整個過程的執行順序,以及一些可以通用的步驟(如讀取XML文件和解析XML數據流),而另一些比較個性的步驟,則由它的繼承類自己去完成(如上例中的「形成工廠」,由於各個工廠各不一樣,因此由各自的繼承類自己去決定它的工廠是怎樣形成的)。 各個繼承類可以根據自己的需要,通過重載重新定義各個步驟函數。但是,模板模式要求不能重載主函數,因此正規的模板模式其主函數應當是final(雖然我們常常不這么寫)。另外,模板模式還允許你定義的這個步驟中,有些步驟是可選步驟。對與可選步驟,我們通常稱為「鉤子(hood)」。它在編寫時,在抽象類中並不是一個抽象函數,但卻是一個什麼都不寫的空函數。繼承類在編寫時,如果需要這個步驟則重載這個函數,否則就什麼也不寫,進而在執行的時候也如同什麼都沒有執行。 通過以上對模板模式的描述可以發現,模板模式可以大大地提高我們的代碼復用程度。 以上一些常用設計模式,都能使我們快速提高代碼質量。還是那句話,設計模式不是什麼高深的東西,恰恰相反,它是初學者快速提高的捷徑。然而,如果說提高代碼復用是提高代碼質量的初階,使用設計模式也只能是提高代碼質量的中階。那麼,什麼是高階呢?我認為是那些分析設計理論,更具體地說,就是職責驅動設計和領域驅動設計。 3)職責驅動設計和領域驅動設計 前面我提到,當我們嘗試寫一些復雜功能的時候,我們把功能分解成一個個相對獨立的函數。但是,應當將這些函數分配到哪個類中呢?也就是系統中的所有類都應當擁有哪些函數呢?或者說應當表現出哪些行為呢?答案就在這里:以職責為中心,根據職責分配行為。我們在分析系統時,首先是根據客戶需求進行用例分析,然後根據用例繪制領域模式和分析模型,整個系統最主要的類就形成了。通過以上分析形成的類,往往和現實世界的對象是對應的。正因為如此,軟體世界的這些類也具有了與現實世界的對象相對應的職責,以及在這些職責范圍內的行為。 職責驅動設計(Responsibility Drive Design,RDD)是Craig Larman在他的經典著作《UML和模式應用》中提出的。職責驅動設計的核心思想,就是我們在對一個系統進行分析設計的時候,應當以職責為中心,根據職責分配行為。這種思想首先要求我們設計的所有軟體世界的對象,應當與現實世界盡量保持一致,他稱之為「低表示差異」。有了低表示差異,一方面提高了代碼的可讀性,另一方面,當業務發生變更的時候,也可以根據實際情況快速應對變更。 Craig Larman在提出職責驅動設計理論的同時,還提出了GRASP設計模式,來豐富這個理論。在GRASP設計模式中,我認為,低耦合、高內聚、信息專家模式最有用。 繼Craig Larman提出的職責驅動設計數年之後,另一位大師提出了領域驅動設計。領域驅動設計(Domain Drive Design,DDD)是Eric Evans在他的同名著作《領域驅動設計》中提出的。在之前的設計理論中,領域模型是從用例模型到分析模型之間的一種中間模型,也就是從需求分析到軟體開發之間的一種中間模型。這么一個中間模型,既不是需求階段的重要產物,在開發階段也不以它作為標准進行開發,僅僅是作為參考,甚至給人感覺有一些多餘。但是,Evans在領域驅動設計中,將它放到了一個無比重要的位置。按照領域驅動設計的理論,在需求分析階段,需求分析人員使用領域模型與客戶進行溝通;在設計開發階段,開發人員使用領域模型指導設計開發;在運行維護和二次開發階段,維護和二次開發人員使用領域模型理解和熟悉系統,並指導他們進行維護和二次開發。總之,在整個軟體開發的生命周期中,領域模型都成為了最核心的內容。 領域驅動設計繼承了職責驅動設計。在領域驅動設計中強調的,依然是低表示差異,以及職責的分配。但是,如何做到低表示差異呢?如何完成職責分配呢?領域驅動設計給了我們完美的答案,那就是建立領域模型。領域驅動設計改變了我們的設計方式。在需求分析階段,用例模型已不再是這個階段的核心,而是建立領域模型。在開發和二次開發階段,開發人員也不再是一埋頭地猛扎進程序堆里開始編程,而是首先細致地進行領域模型分析。領域驅動設計強調持續精化,使領域模型不再是一旦完成分析就扔在一邊不再理會的圖紙,而是在不斷理解業務的基礎上不斷修改和精化領域模型,進而驅動我們代碼的精化。領域驅動設計強調的不再是一次軟體開發過程中我們要做的工作,它看得更加長遠,它強調的是一套軟體在相當長一段時間內持續升級的過程中我們應當做的工作。我認為,領域驅動設計是提高代碼質量的最高等級。當時,使用領域驅動設計進行軟體開發是一場相當巨大的改革,它顛覆了我們過去的所有開發模式,我們必須腳踏實地地一步一步去實踐和改變。 職責驅動設計 隨著軟體業的不斷發展,隨著軟體需求的不斷擴大,軟體所管理的范圍也在不斷拓寬。過去一個軟體僅僅管理一台電腦的一個小小的功能,而現在被擴展到了一個企業、一個行業、一個產業鏈。過去我們開發一套軟體,只有少量的二次開發,當它使用到一定時候我們就拋棄掉重新又開發一套。現在,隨著用戶對軟體依賴程度的不斷加大,我們很難說拋棄一套軟體重新開發了,更多的是在一套軟體中持續改進,使這套軟體的生命周期持續數年以及數個版本。正是因為軟體業面臨著如此巨大的壓力,我們的代碼質量,我們開發的軟體擁有的可變更性和持續改進的能力,成為軟體制勝的關鍵因素,令我們不能不反思。 代碼質量評價的關鍵指標:低耦合,高內聚 耦合就是對某元素與其它元素之間的連接、感知和依賴的量度。耦合包括: 1.元素B是元素A的屬性,或者元素A引用了元素B的實例(這包括元素A調用的某個方法,其參數中包含元素B)。 2.元素A調用了元素B的方法。 3.元素A直接或間接成為元素B的子類。 4.元素A是介面B的實現。 如果一個元素過於依賴其它元素,一旦它所依賴的元素不存在,或者發生變更,則該元素將不能再正常運行,或者不得不相應地進行變更。因此,耦合將大大影響代碼的通用性和可變更性。 內聚,更為專業的說法叫功能內聚,是對軟體系統中元素職責相關性和集中度的度量。如果元素具有高度相關的職責,除了這些職責內的任務,沒有其它過多的工作,那麼該元素就具有高內聚性,反之則為低內聚性。內聚就像一個專橫的管理者,它只做自己職責范圍內的事,而將其它與它相關的事情,分配給別人去做。 高質量的代碼要求我們的代碼保持低耦合、高內聚。但是,這個要求是如此的抽象與模糊,如何才能做到這些呢?軟體大師們告訴我們了許多方法,其中之一就是Craig Larman的職責驅動設計。 職責驅動設計(Responsibility Drive Design,RDD)是Craig Larman在他的經典著作《UML和模式應用》中提出的。要理解職責驅動設計,我們首先要理解「低表示差異」。 低表示差異 我們開發的應用軟體實際上是對現實世界的模擬,因此,軟體世界與現實世界存在著必然的聯系。當我們在進行需求分析的時候,需求分析員實際上是從客戶那裡在了解現實世界事物的規則、工作的流程。如果我們在軟體分析和設計的過程中,將軟體世界與現實世界緊密地聯繫到一起,我們的軟體將更加本色地還原事物最本質的規律。這樣的設計,就稱之為「低表示差異」。 採用「低表示差異」進行軟體設計,現實世界有什麼事物,就映射為軟體世界的各種對象(類);現實世界的事物擁有什麼樣的職責,在軟體世界裡的對象就擁有什麼樣的職責;在現實世界中的事物,因為它的職責而產生的行為,在軟體世界中就反映為對象所擁有的函數。 低表示差異,使分析設計者對軟體的分析和設計更加簡單,思路更加清晰;使代碼更加可讀,閱讀者更加易於理解;更重要的是
⑨ 如何提高C++代碼質量
使用集成插件 pc-lint,可以實時監測代碼規范。
提高編碼思想推薦看下effective C++: http://download.csdn.net/detail/u010745238/7028005
⑩ 北大青鳥java培訓:Java代碼質量如何提升
對於一個Java程序員來說,Java代碼質量是一定要追求的。
如果你不能夠保證自己的Java代碼的質量,想必局戚岩你很難在一家公司待得長久,並且有很大的晉升發展空間。
Java代碼質量如何提升?安徽電腦培訓http://www.kmbdqn.cn/認為作為一個Java程序員,這是你必須時常思考,並且還是得採取行動仔皮切實提升的。
Java代碼質量如何提升?你時常跟Java代碼打交道,你覺得什麼樣子的Java代碼是具備高質量的呢?高滿足需求性,高度理解性,高度可測試性,高度可擴展性,高度可維護性等等,那麼很多人大致的概念是有的,但是具體是怎麼樣的,還是有點懵的,那麼就讓北大青鳥小編具體為你舉下例子。
比如高滿足需求性,你所編寫的Java代碼,如果不能夠滿足客戶的需求,那麼很多時候它就是廢的,桐御盡管在你眼中它相當的完美,但是你所編寫的Java代碼一定是能夠滿足客戶需求的。
高度理解性,就是你所編寫的Java代碼,不能夠就你一個人看懂就行了,你還得有的地方稍加註釋,讓其他的人也理解,讓其他人可讀。
Java代碼的高度可測試性:是指軟體發現故障並隔離定位其故障的能力特性,以及在一定的時間或成本的前提條件下,進行測試的能力。
Java代碼高度可擴展性:即預留以後變更代碼的空間。
Java代碼高度可維護性:軟體研發完了,是研發階段的終止,卻是軟體運營維護的開始。