高質(zhì)量編程演示文稿_第1頁(yè)
高質(zhì)量編程演示文稿_第2頁(yè)
高質(zhì)量編程演示文稿_第3頁(yè)
高質(zhì)量編程演示文稿_第4頁(yè)
高質(zhì)量編程演示文稿_第5頁(yè)
已閱讀5頁(yè),還剩92頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

高質(zhì)量編程演示文稿1第一頁(yè),共九十七頁(yè)。高質(zhì)量編程2第二頁(yè),共九十七頁(yè)。內(nèi)容提要8.1 代碼風(fēng)格 8.1.1 程序的書寫格式 8.1.2 Windows程序命名規(guī)則8.1.3 共性規(guī)則8.1.4 表達(dá)式和基本語(yǔ)句 8.2 函數(shù)設(shè)計(jì)規(guī)則 8.2.1 函數(shù)外部特性的注釋規(guī)則 8.2.2 參數(shù)規(guī)則 8.2.3 返回值的規(guī)則 8.2.4 函數(shù)內(nèi)部的實(shí)現(xiàn)規(guī)則 8.3 提高程序質(zhì)量的技術(shù) 8.3.1 內(nèi)存管理規(guī)則 8.3.2 面向?qū)ο蟮脑O(shè)計(jì)規(guī)則 8.4 代碼審查 8.4.1 代碼審查的主要工作 8.4.2 代碼審查的流程 8.4.3 Java代碼審查的常見錯(cuò)誤 8.5 小結(jié) 第三頁(yè),共九十七頁(yè)。8.1 代碼風(fēng)格統(tǒng)一編程風(fēng)格的意義很大,是一個(gè)優(yōu)秀而且職業(yè)化的開發(fā)團(tuán)隊(duì)所必需的素質(zhì)。增加開發(fā)過程代碼的強(qiáng)壯性、可讀性、易維護(hù)性。減少有經(jīng)驗(yàn)和無經(jīng)驗(yàn)開發(fā)人員編程所需的腦力工作,為軟件的良好維護(hù)性打下好的基礎(chǔ)。通過人為以及自動(dòng)的方式對(duì)最終軟件應(yīng)用質(zhì)量標(biāo)準(zhǔn),使新的開發(fā)人員快速適應(yīng)項(xiàng)目氛圍。支持項(xiàng)目資源的復(fù)用:允許開發(fā)人員從一個(gè)項(xiàng)目區(qū)域移動(dòng)到另一個(gè),而不需要重新適應(yīng)新的子項(xiàng)目團(tuán)隊(duì)的氛圍。第四頁(yè),共九十七頁(yè)。8.1.1 程序的書寫格式版本的聲明格式////Copyright@2011,北京侏羅紀(jì)公司XX部//Allrightsreserved.////文件名稱:filename.h//文件標(biāo)識(shí):見配置管理計(jì)劃書//摘要:簡(jiǎn)要描述本文件的內(nèi)容///當(dāng)前版本:2.1//作者:輸入作者名字//完成日期:2011年3月20日////取代版本:2.0//原作者:輸入原作者名字//完成日期:2011年2月10日//第五頁(yè),共九十七頁(yè)。頭文件的書寫格式頭文件必須包含下列內(nèi)容:頭文件開頭處的版權(quán)和版本聲明。預(yù)處理塊。函數(shù)和類結(jié)構(gòu)聲明等。//版權(quán)和版本聲明見示例1-1。#ifndefGRAPHICS_H//防止graphics.h被重復(fù)引用#defineGRAPHICS_H#include<math.h>//引用標(biāo)準(zhǔn)庫(kù)的頭文件

…#include“myheader.h”//引用非標(biāo)準(zhǔn)庫(kù)的頭文件

…voidFunction1(…);//全局函數(shù)聲明

…classBox //類結(jié)構(gòu)聲明{ …};#endif第六頁(yè),共九十七頁(yè)。定義文件的書寫格式定義文件的書寫格式:必須包含三部分內(nèi)容:定義文件開頭處的版權(quán)和版本聲明;對(duì)一些頭文件的引用;程序的實(shí)現(xiàn)體(包括數(shù)據(jù)和代碼)。//版權(quán)和版本聲明見示例1-1,此處省略。#include“graphics.h” //引用頭文件

…//全局函數(shù)的實(shí)現(xiàn)體voidFunction1(…){ …}//類成員函數(shù)的實(shí)現(xiàn)體voidDraw(…){ …}第七頁(yè),共九十七頁(yè)??招械氖褂?/空行//空行voidFunction1(…){ …}//空行//空行voidFunction2(…){ …}//空行//空行voidFunction3(…){ …}//空行While(condition){ statement1;

//空行

if(condition) { statement2;

} else { statement3;

}//空行

statement4;}第八頁(yè),共九十七頁(yè)。

VoidFunc1(intx,inty,intz);//良好的風(fēng)格voidFunc1(intx,inty,intz);//不良的風(fēng)格if(year>=2000)//良好的風(fēng)格if(year>=2000)//不良的風(fēng)格if((a>=b)&&(c<=d))//良好的風(fēng)格if(a>=b&&c<=d)//不良的風(fēng)格for(i=0;i<10;i++)//良好的風(fēng)格for(i=0;i<10;i++)//不良的風(fēng)格for(I=0;I<10;i++)//過多的空格x=a<b?a:b;//良好的風(fēng)格x=a<b?a:b;//不好的風(fēng)格int*x=&y;//良好的風(fēng)格int*x=&y;//不良的風(fēng)格array[5]=0;//不要寫成array[5]=0;a.Function();//不要寫成a.Function();b->Function();//不要寫成b->Function();代碼行內(nèi)的空格第九頁(yè),共九十七頁(yè)。8.1.2 Windows程序命名規(guī)則匈牙利命名法是一種編程時(shí)的命名規(guī)范?;驹瓌t是:變量名=屬性+類型+對(duì)象描述,其中每一對(duì)象的名稱都要求有明確含義,可以取對(duì)象名字全稱或名字的一部分。命名要基于容易記憶容易理解的原則。保證名字的連貫性是非常重要的。舉例來說,表單的名稱為form,那么在匈牙利命名法中可以簡(jiǎn)寫為frm,則當(dāng)表單變量名稱為Switchboard時(shí),變量全稱應(yīng)該為frmSwitchboard。這樣可以很容易從變量名看出Switchboard是一個(gè)表單,同樣,如果此變量類型為標(biāo)簽,那么就應(yīng)命名成lblSwitchboard??梢钥闯?,匈牙利命名法非常便于記憶,而且使變量名非常清晰易懂,這樣,增強(qiáng)了代碼的可讀性,方便各程序員之間相互交流代碼。據(jù)說這種命名法是一位叫CharlesSimonyi的匈牙利程序員發(fā)明的,后來他在微軟呆了幾年,于是這種命名法就通過微軟的各種產(chǎn)品和文檔資料向世界傳播開了?,F(xiàn)在,大部分程序員不管自己使用什么軟件進(jìn)行開發(fā),或多或少都使用了這種命名法。第十頁(yè),共九十七頁(yè)。常用的數(shù)據(jù)類型前綴前綴類型例子bBOOLbIsParentby,byteBYTEbyFlag,byteFlagchcharchTextfn函數(shù)變量fnCallbackhHANDLE(句柄)hWndiintiValuenintnValueuunsignedintuFlagdwDWORDdwDatap指針pBuffersz,str字符串szBufferlpstr,lpszLPSTRlpstrMessagewWORDwDatax,y坐標(biāo)xPos,yPosm_類成員變量m_bFlag,m_nValg_全局變量g_bFlag,g_nMsg第十一頁(yè),共九十七頁(yè)。常用的控件名前綴前綴控件類型frm,wnd窗口cmd,btn按鈕cmb,combo下拉式列表框txt文本輸入框lbl標(biāo)簽grdGrid,網(wǎng)格scr滾動(dòng)條lst列表框frame框架第十二頁(yè),共九十七頁(yè)。8.1.3 共性規(guī)則[提示1]較短的單詞可通過去掉“元音”形成縮寫;較長(zhǎng)的單詞可取單詞的頭幾個(gè)字母形成縮寫;一些單詞有大家公認(rèn)的縮寫。示例:如下單詞的縮寫能夠被大家基本認(rèn)可。temp可縮寫為tmp;flag可縮寫為flg;statistic可縮寫為stat;increment可縮寫為inc;message可縮寫為msg;[提示2]應(yīng)該在源文件的開始之處,對(duì)文件中所使用的縮寫或約定,特別是特殊的縮寫,進(jìn)行必要的注釋說明。標(biāo)識(shí)符最好采用英文單詞或其組合,便于記憶和閱讀,可望文知意,不必進(jìn)行“解碼”。不能使用漢語(yǔ)拼音來命名。程序中的英文單詞一般不會(huì)太復(fù)雜,用詞應(yīng)當(dāng)準(zhǔn)確。例如不要把CurrentValue寫成NowValue。第十三頁(yè),共九十七頁(yè)。8.1.4 表達(dá)式和基本語(yǔ)句1.表達(dá)式與復(fù)合表達(dá)式[示例]如下表達(dá)式,考慮不周就可能出問題,也較難理解。

*stat_poi+++=1; *++stat_poi+=1;應(yīng)分別改為如下。 *stat_poi+=1;

stat_poi++;//此二語(yǔ)句功能相當(dāng)于“*stat_poi+++=1;”和

++stat_poi;*stat_poi+=1;//此二語(yǔ)句功能相當(dāng)于“*++stat_poi+=1;”第十四頁(yè),共九十七頁(yè)。if語(yǔ)句假設(shè)布爾變量名字為flag,它與零值比較的標(biāo)準(zhǔn)if語(yǔ)句如下:if(flag) //表示flag為真if(!flag) //表示flag為假其它的用法都屬于不良風(fēng)格,例如:if(flag==TRUE) if(flag==1) if(flag==FALSE)if(flag==0) //我覺得應(yīng)該采用if(flag==TRUE)來表示,賦值用flag=TRUE;//因?yàn)椴煌僮飨到y(tǒng)的TRUE和FALSE不一樣,如WINDOWS里TRUE是1而有些系統(tǒng)//TRUE是0cyj應(yīng)當(dāng)將整型變量用“==”或“!=”直接與0比較。假設(shè)整型變量的名字為value,它與零值比較的標(biāo)準(zhǔn)if語(yǔ)句如下:if(value==0)if(value!=0)不可模仿布爾變量的風(fēng)格而寫成if(value) //會(huì)讓人誤解value是布爾變量if(!value)不可將浮點(diǎn)變量用“==”或“!=”與任何數(shù)字比較。第十五頁(yè),共九十七頁(yè)。循環(huán)語(yǔ)句的效率For(row=0;row<100;row++){for(col=0;col<5;col++){sum=sum+a[row][col];}}for(col=0;col<5;col++){for(row=0;row<100;row++){sum=sum+a[row][col];}}第十六頁(yè),共九十七頁(yè)。建議【建議】如果循環(huán)體內(nèi)存在邏輯判斷,并且循環(huán)次數(shù)很大,宜將邏輯判斷移到循環(huán)體的外面。例如,下面代碼:for(I=0;i<N;I++){if(condition)DoSomething();ElseDoOtherthing();}if(condition){for(i=0;i<N;i++)

DoSomething();}else{for(i=0;i<N;i++)

DoOtherthing();}第十七頁(yè),共九十七頁(yè)。建議【建議】for語(yǔ)句的循環(huán)控制變量的取值采用“半開半閉區(qū)間”寫法。例如for(x=0;x<N;x++){ …}for(x=0;x<=N-1;x++){ …}第十八頁(yè),共九十七頁(yè)。C++類中的常量不能在類聲明中初始化const數(shù)據(jù)成員。以下用法是錯(cuò)誤的,因?yàn)轭惖膶?duì)象未被創(chuàng)建時(shí),編譯器不知道SIZE的值是什么。classA {…constintSIZE=100; //錯(cuò)誤,企圖在類聲明中初始化const數(shù)據(jù)成員

intarray[SIZE]; //錯(cuò)誤,未知的SIZE };const數(shù)據(jù)成員的初始化只能在類構(gòu)造函數(shù)的初始化表中進(jìn)行,例如classA {… A(intsize); //構(gòu)造函數(shù)

constintSIZE;

};A::A(intsize):SIZE(size) //構(gòu)造函數(shù)的初始化表

{ … } Aa(100); //對(duì)象a的SIZE值為100 Ab(200); //對(duì)象b的SIZE值為200第十九頁(yè),共九十七頁(yè)。8.2 函數(shù)設(shè)計(jì)規(guī)則函數(shù)是C++/C程序的基本功能單元,其重要性不言而喻。函數(shù)設(shè)計(jì)的細(xì)微缺點(diǎn)很容易導(dǎo)致該函數(shù)被錯(cuò)用,所以光使函數(shù)的功能正確是不夠的。函數(shù)接口的兩個(gè)要素是參數(shù)和返回值。C++語(yǔ)言中,函數(shù)的參數(shù)和返回值的傳遞方式有三種:值傳遞(passbyvalue)、指針傳遞(passbypointer)、引用傳遞(passbyreference)。第二十頁(yè),共九十七頁(yè)。8.2.1 函數(shù)外部特性的注釋規(guī)則函數(shù)外部特性注釋必須在函數(shù)體上部采用中文說明,標(biāo)準(zhǔn)格式如下://輸入?yún)?shù):// 參數(shù)1: (指出參數(shù)的物理意義、量綱、取值范圍等信息)// ……// 參數(shù)N:// ……//函數(shù)返回:// …… (指出返回值的物理意義、量綱、取值范圍等信息)//功能描述:// ……//注意事項(xiàng):// ……第二十一頁(yè),共九十七頁(yè)。8.2.2 參數(shù)規(guī)則[建議]對(duì)僅作為輸入的參數(shù),盡量使用const修飾符。如果輸入?yún)?shù)以值傳遞的方式傳遞對(duì)象,則宜改用“const&”方式來傳遞,這樣可以省去臨時(shí)對(duì)象的構(gòu)造和析構(gòu)過程,從而提高效率。參數(shù)缺省值只能出現(xiàn)在函數(shù)的聲明中,而不能出現(xiàn)在定義體中。例如: voidFoo(intx=0,inty=0); //正確,缺省值出現(xiàn)在函數(shù)的聲明中 voidFoo(intx=0,inty=0) //錯(cuò)誤,缺省值出現(xiàn)在函數(shù)的定義體中 { }如果函數(shù)有多個(gè)參數(shù),參數(shù)只能從后向前挨個(gè)兒缺省,否則將導(dǎo)致函數(shù)調(diào)用語(yǔ)句怪模怪樣。例如:voidFoo(intx,inty=0,intz=0); //正確voidFoo(intx=0,inty,intz=0); //錯(cuò)誤【建議】避免函數(shù)有太多的參數(shù),參數(shù)個(gè)數(shù)盡量控制在5個(gè)以內(nèi)。如果參數(shù)太多,在使用時(shí)容易將參數(shù)類型或順序搞錯(cuò)?!窘ㄗh】盡量不要使用類型和數(shù)目不確定的參數(shù)。C標(biāo)準(zhǔn)庫(kù)函數(shù)printf是采用不確定參數(shù)的典型代表,其原型為:

intprintf(constchat*format[,argument]…); 這種風(fēng)格的函數(shù)在編譯時(shí)喪失了嚴(yán)格的類型安全檢查?!窘ㄗh】非調(diào)度函數(shù)應(yīng)減少或防止控制參數(shù),盡量只使用數(shù)據(jù)參數(shù)。該規(guī)則可降低代碼的控制耦合。第二十二頁(yè),共九十七頁(yè)。8.2.3 返回值的規(guī)則【建議】有時(shí)候函數(shù)原本不需要返回值,但為了增加靈活性如支持鏈?zhǔn)奖磉_(dá),可以附加返回值。【建議】如果函數(shù)的返回值是一個(gè)對(duì)象,有些場(chǎng)合用“引用傳遞”替換“值傳遞”可以提高效率。而有些場(chǎng)合只能用“值傳遞”而不能用“引用傳遞”,否則會(huì)出錯(cuò)。【建議】函數(shù)要盡量只有一個(gè)返回點(diǎn)。不能返回引用和指針到局部對(duì)象。[說明]離開函數(shù)作用域時(shí)會(huì)銷毀局部對(duì)象;使用銷毀了的對(duì)象會(huì)造成災(zāi)難。不可返回由new初始化,之后又已解除引用的指針。[說明]由于支持鏈?zhǔn)奖磉_(dá)式,造成返回對(duì)象不能刪除,導(dǎo)致內(nèi)存泄漏。第二十三頁(yè),共九十七頁(yè)。8.2.4 函數(shù)內(nèi)部的實(shí)現(xiàn)規(guī)則[提示]在同一項(xiàng)目組應(yīng)明確規(guī)定對(duì)接口函數(shù)參數(shù)的合法性檢查應(yīng)由函數(shù)的調(diào)用者負(fù)責(zé)還是由接口函數(shù)本身負(fù)責(zé),缺省是由函數(shù)調(diào)用者負(fù)責(zé)。說明:對(duì)于模塊間接口函數(shù)的參數(shù)的合法性檢查這一問題,往往有兩個(gè)極端現(xiàn)象,即:要么是調(diào)用者和被調(diào)用者對(duì)參數(shù)均不作合法性檢查,結(jié)果就遺漏了合法性檢查這一必要的處理過程,造成問題隱患;要么就是調(diào)用者和被調(diào)用者均對(duì)參數(shù)進(jìn)行合法性檢查,這種情況雖不會(huì)造成問題,但產(chǎn)生了冗余代碼,降低了效率。(C++代碼)使operator=檢查自賦值。[說明]執(zhí)行檢查有兩點(diǎn)重要的理由:首先,派生類對(duì)象的賦值涉及到調(diào)用每一個(gè)基類(在繼承層次結(jié)構(gòu)中位于此類的上方)的賦值操作符,跳過這些操作符就可以節(jié)省很多運(yùn)行時(shí)間。其次,在復(fù)制“rvalue”對(duì)象前,賦值涉及到解構(gòu)“l(fā)value”對(duì)象。在自賦值時(shí),rvalue對(duì)象在賦值前就已銷毀了,因此賦值的結(jié)果是不確定的。第二十四頁(yè),共九十七頁(yè)。8.3 提高程序質(zhì)量的技術(shù)8.3.1 內(nèi)存管理規(guī)則BillGates在1981年曾經(jīng)說過:640Koughttobeenoughforeverybody。程序員們經(jīng)常編寫內(nèi)存管理程序,往往提心吊膽。同時(shí),由于個(gè)人編程的習(xí)慣性缺陷,導(dǎo)致同類問題重復(fù)出現(xiàn),如果不想觸雷,唯一的解決辦法就是發(fā)現(xiàn)所有潛伏的地雷并且排除它們。第二十五頁(yè),共九十七頁(yè)。內(nèi)存分配方式按照內(nèi)存分配的位置不同,內(nèi)存分配方式有三種:從靜態(tài)存儲(chǔ)區(qū)域分配。內(nèi)存在程序編譯的時(shí)候就已經(jīng)分配好,這塊內(nèi)存在程序的整個(gè)運(yùn)行期間都存在。例如全局變量,static變量。在棧上創(chuàng)建。在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲(chǔ)單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí)這些存儲(chǔ)單元自動(dòng)被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但是分配的內(nèi)存容量有限。從堆上分配,亦稱動(dòng)態(tài)內(nèi)存分配。程序在運(yùn)行的時(shí)候用malloc或new申請(qǐng)任意多少的內(nèi)存,程序員自己負(fù)責(zé)在何時(shí)用free或delete釋放內(nèi)存。動(dòng)態(tài)內(nèi)存的生存期由我們決定,使用非常靈活,但問題也最多。第二十六頁(yè),共九十七頁(yè)。常見的錯(cuò)誤情況內(nèi)存分配未成功,卻使用了它。內(nèi)存分配雖然成功,但是尚未初始化就引用它。內(nèi)存分配成功并且已經(jīng)初始化,但操作越過了內(nèi)存的邊界。忘記了釋放內(nèi)存,造成內(nèi)存泄露。釋放了內(nèi)存卻繼續(xù)使用它。程序中的對(duì)象調(diào)用關(guān)系過于復(fù)雜,實(shí)在難以搞清楚某個(gè)對(duì)象究竟是否已經(jīng)釋放了內(nèi)存,此時(shí)應(yīng)該重新設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu),從根本上解決對(duì)象管理的混亂局面。函數(shù)的return語(yǔ)句寫錯(cuò)了,注意不要返回指向“棧內(nèi)存”的“指針”或者“引用”,因?yàn)樵搩?nèi)存在函數(shù)體結(jié)束時(shí)被自動(dòng)銷毀。使用free或delete釋放了內(nèi)存后,沒有將指針設(shè)置為NULL。導(dǎo)致產(chǎn)生“野指針”。用malloc或new申請(qǐng)內(nèi)存之后,應(yīng)該立即檢查指針值是否為NULL。防止使用指針值為NULL的內(nèi)存。第二十七頁(yè),共九十七頁(yè)。注意事項(xiàng)不要忘記為數(shù)組和動(dòng)態(tài)內(nèi)存賦初值。防止將未被初始化的內(nèi)存作為右值使用。避免數(shù)組或指針的下標(biāo)越界,特別要當(dāng)心發(fā)生“多1”或者“少1”操作。動(dòng)態(tài)內(nèi)存的申請(qǐng)與釋放必須配對(duì),防止內(nèi)存泄漏。用free或delete釋放了內(nèi)存之后,立即將指針設(shè)置為NULL,防止產(chǎn)生“野指針”。malloc返回值的類型是void*,所以在調(diào)用malloc時(shí)要顯式地進(jìn)行類型轉(zhuǎn)換,將void*轉(zhuǎn)換成所需要的指針類型。用delete釋放對(duì)象數(shù)組時(shí),留意不要丟了符號(hào)。檢查程序中內(nèi)存申請(qǐng)/釋放操作的成對(duì)性,防止內(nèi)存泄漏。第二十八頁(yè),共九十七頁(yè)。指針與數(shù)組的區(qū)別chara[]=“hello”;a[0]=‘X’;cout<<a<<endl;char*p=“world”;//注意p指向常量字符串p[0]=‘X’;//編譯器不能發(fā)現(xiàn)該錯(cuò)誤cout<<p<<endl;第二十九頁(yè),共九十七頁(yè)。內(nèi)存中指針參數(shù)的傳遞voidGetMemory(char*p,intnum){p=(char*)malloc(sizeof(char)*num);}voidTest(void){char*str=NULL;GetMemory(str,100);//str仍然為NULLstrcpy(str,"hello");//運(yùn)行錯(cuò)誤}第三十頁(yè),共九十七頁(yè)。示例用指向指針的指針申請(qǐng)動(dòng)態(tài)內(nèi)存如果非得要用指針參數(shù)去申請(qǐng)內(nèi)存,那么應(yīng)該改用“指向指針的指針”,見示例。voidGetMemory2(char**p,intnum){*p=(char*)malloc(sizeof(char)*num);}voidTest2(void){char*str=NULL;

GetMemory2(&str,100);//注意參數(shù)是&str,而不是strstrcpy(str,"hello");

cout<<str<<endl;

free(str);}第三十一頁(yè),共九十七頁(yè)。8.3.2 面向?qū)ο蟮脑O(shè)計(jì)規(guī)則比較面向?qū)ο蟪绦蛟O(shè)計(jì)和面向過程程序設(shè)計(jì),還可以得到面向?qū)ο蟪绦蛟O(shè)計(jì)的其他優(yōu)點(diǎn):數(shù)據(jù)抽象的概念可以在保持外部接口不變的情況下改變內(nèi)部實(shí)現(xiàn),從而減少甚至避免對(duì)外界的干擾;通過繼承大幅減少冗余的代碼,并可以方便地?cái)U(kuò)展現(xiàn)有代碼,提高編碼效率,也減低了出錯(cuò)概率,降低軟件維護(hù)的難度;結(jié)合面向?qū)ο蠓治?、面向?qū)ο笤O(shè)計(jì),允許將問題域中的對(duì)象直接映射到程序中,減少軟件開發(fā)過程中中間環(huán)節(jié)的轉(zhuǎn)換過程;通過對(duì)對(duì)象的辨別、劃分可以將軟件系統(tǒng)分割為若干相對(duì)為獨(dú)立的部分,在一定程度上更便于控制軟件復(fù)雜度;以對(duì)象為中心的設(shè)計(jì)可以幫助開發(fā)人員從靜態(tài)(屬性)和動(dòng)態(tài)(方法)兩個(gè)方面把握問題,從而更好地實(shí)現(xiàn)系統(tǒng);通過對(duì)象的聚合、聯(lián)合可以在保證封裝與抽象的原則下實(shí)現(xiàn)對(duì)象在內(nèi)在結(jié)構(gòu)以及外在功能上的擴(kuò)充,從而實(shí)現(xiàn)對(duì)象由低到高的升級(jí)。第三十二頁(yè),共九十七頁(yè)。面向?qū)ο笤O(shè)計(jì)原則概述軟件的可維護(hù)性和可復(fù)用性知名軟件大師RobertC.Martin認(rèn)為一個(gè)可維護(hù)性較低的軟件設(shè)計(jì),通常由于如下四個(gè)原因造成:過于僵硬(Rigidity)過于脆弱(Fragility)復(fù)用率低(Immobility)黏度過高(Viscosity)RobertC.Martin第三十三頁(yè),共九十七頁(yè)。面向?qū)ο笤O(shè)計(jì)原則概述軟件的可維護(hù)性和可復(fù)用性軟件工程和建模大師PeterCoad認(rèn)為,一個(gè)好的系統(tǒng)設(shè)計(jì)應(yīng)該具備如下三個(gè)性質(zhì):可擴(kuò)展性(Extensibility)靈活性(Flexibility)可插入性(Pluggability)

PeterCoad第三十四頁(yè),共九十七頁(yè)。面向?qū)ο笤O(shè)計(jì)原則概述軟件的可維護(hù)性和可復(fù)用性

軟件的復(fù)用(Reuse)或重用擁有眾多優(yōu)點(diǎn),如可以提高軟件的開發(fā)效率,提高軟件質(zhì)量,節(jié)約開發(fā)成本,恰當(dāng)?shù)膹?fù)用還可以改善系統(tǒng)的可維護(hù)性。面向?qū)ο笤O(shè)計(jì)復(fù)用的目標(biāo)在于實(shí)現(xiàn)支持可維護(hù)性的復(fù)用。

在面向?qū)ο蟮脑O(shè)計(jì)里面,可維護(hù)性復(fù)用都是以面向?qū)ο笤O(shè)計(jì)原則為基礎(chǔ)的,這些設(shè)計(jì)原則首先都是復(fù)用的原則,遵循這些設(shè)計(jì)原則可以有效地提高系統(tǒng)的復(fù)用性,同時(shí)提高系統(tǒng)的可維護(hù)性。第三十五頁(yè),共九十七頁(yè)。面向?qū)ο笤O(shè)計(jì)原則概述軟件的可維護(hù)性和可復(fù)用性面向?qū)ο笤O(shè)計(jì)原則和設(shè)計(jì)模式也是對(duì)系統(tǒng)進(jìn)行合理重構(gòu)的指南針,重構(gòu)(Refactoring)是在不改變軟件現(xiàn)有功能的基礎(chǔ)上,通過調(diào)整程序代碼改善軟件的質(zhì)量、性能,使其程序的設(shè)計(jì)模式和架構(gòu)更趨合理,提高軟件的擴(kuò)展性和維護(hù)性。MartinFowler第三十六頁(yè),共九十七頁(yè)。面向?qū)ο笤O(shè)計(jì)原則概述面向?qū)ο笤O(shè)計(jì)原則簡(jiǎn)介常用的面向?qū)ο笤O(shè)計(jì)原則包括七個(gè),這些原則并不是孤立存在的,它們相互依賴,相互補(bǔ)充。設(shè)計(jì)原則名稱設(shè)計(jì)原則簡(jiǎn)介重要性單一職責(zé)原則(SingleResponsibilityPrinciple,SRP)類的職責(zé)要單一,不能將太多的職責(zé)放在一個(gè)類中。★★★★☆開閉原則(Open-ClosedPrinciple,OCP)軟件實(shí)體對(duì)擴(kuò)展是開放的,但對(duì)修改是關(guān)閉的,即在不修改一個(gè)軟件實(shí)體的基礎(chǔ)上去擴(kuò)展其功能?!铩铩铩铩锢锸洗鷵Q原則(LiskovSubstitutionPrinciple,LSP)在軟件系統(tǒng)中,一個(gè)可以接受基類對(duì)象的地方必然可以接受一個(gè)子類對(duì)象?!铩铩铩铩钜蕾嚨罐D(zhuǎn)原則(DependencyInversionPrinciple,DIP)要針對(duì)抽象層編程,而不要針對(duì)具體類編程?!铩铩铩铩锝涌诟綦x原則(InterfaceSegregationPrinciple,ISP)使用多個(gè)專門的接口來取代一個(gè)統(tǒng)一的接口?!铩铩睢睢詈铣蓮?fù)用原則(CompositeReusePrinciple,CRP)在系統(tǒng)中應(yīng)該盡量多使用組合和聚合關(guān)聯(lián)關(guān)系,盡量少使用甚至不使用繼承關(guān)系。★★★★☆迪米特法則(LawofDemeter,LoD)一個(gè)軟件實(shí)體對(duì)其他實(shí)體的引用越少越好,或者說如果兩個(gè)類不必彼此直接通信,那么這兩個(gè)類就不應(yīng)當(dāng)發(fā)生直接的相互作用,而是通過引入一個(gè)第三者發(fā)生間接交互?!铩铩铩睢畹谌唔?yè),共九十七頁(yè)。單一職責(zé)原則單一職責(zé)原則定義單一職責(zé)原則(SingleResponsibilityPrinciple,SRP)定義如下:在軟件系統(tǒng)中,一個(gè)類只負(fù)責(zé)一個(gè)功能領(lǐng)域中的相應(yīng)職責(zé)。另一種定義方式如下:就一個(gè)類而言,應(yīng)該僅有一個(gè)引起它變化的原因。

第三十八頁(yè),共九十七頁(yè)。單一職責(zé)原則單一職責(zé)原則分析一個(gè)類(或者大到模塊,小到方法)承擔(dān)的職責(zé)越多,它被復(fù)用的可能性越小。而且如果一個(gè)類承擔(dān)的職責(zé)過多,就相當(dāng)于將這些職責(zé)耦合在一起,當(dāng)其中一個(gè)職責(zé)變化時(shí),可能會(huì)影響其他職責(zé)的運(yùn)作。類的職責(zé)主要包括兩個(gè)方面:數(shù)據(jù)職責(zé)和行為職責(zé),數(shù)據(jù)職責(zé)通過其屬性來體現(xiàn),而行為職責(zé)通過其方法來體現(xiàn)。單一職責(zé)原則是實(shí)現(xiàn)高內(nèi)聚、低耦合的指導(dǎo)方針,在很多代碼重構(gòu)手法中都能找到它的存在,它是最簡(jiǎn)單但又最難運(yùn)用的原則,需要設(shè)計(jì)人員發(fā)現(xiàn)類的不同職責(zé)并將其分離,而發(fā)現(xiàn)類的多重職責(zé)需要設(shè)計(jì)人員具有較強(qiáng)的分析設(shè)計(jì)能力和相關(guān)重構(gòu)經(jīng)驗(yàn)。第三十九頁(yè),共九十七頁(yè)。單一職責(zé)原則單一職責(zé)原則實(shí)例實(shí)例說明某基于Java的C/S系統(tǒng)的“登錄功能”通過如下登錄類(Login)實(shí)現(xiàn):現(xiàn)使用單一職責(zé)原則對(duì)其進(jìn)行重構(gòu)。第四十頁(yè),共九十七頁(yè)。單一職責(zé)原則單一職責(zé)原則實(shí)例實(shí)例解析使用單一職責(zé)原則重構(gòu)后的類圖:第四十一頁(yè),共九十七頁(yè)。開閉原則開閉原則定義開閉原則(Open-ClosedPrinciple,OCP)定義如下:一個(gè)軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉。也就是說在設(shè)計(jì)一個(gè)模塊的時(shí)候,應(yīng)當(dāng)使這個(gè)模塊可以在不被修改的前提下被擴(kuò)展,即實(shí)現(xiàn)在不修改源代碼的情況下改變這個(gè)模塊的行為。第四十二頁(yè),共九十七頁(yè)。開閉原則開閉原則分析開閉原則由BertrandMeyer于1988年提出,它是面向?qū)ο笤O(shè)計(jì)中最重要的原則之一。在開閉原則的定義中,軟件實(shí)體可以指一個(gè)軟件模塊、一個(gè)由多個(gè)類組成的局部結(jié)構(gòu)或一個(gè)獨(dú)立的類。第四十三頁(yè),共九十七頁(yè)。開閉原則開閉原則分析抽象化是開閉原則的關(guān)鍵。絕大部分的設(shè)計(jì)模式都符合開閉原則,在對(duì)每一個(gè)模式進(jìn)行優(yōu)缺點(diǎn)評(píng)價(jià)時(shí)都會(huì)以開閉原則作為一個(gè)重要的評(píng)價(jià)依據(jù),以判斷基于該模式設(shè)計(jì)的系統(tǒng)是否具備良好的靈活性和可擴(kuò)展性。第四十四頁(yè),共九十七頁(yè)。開閉原則開閉原則實(shí)例

實(shí)例說明某圖形界面系統(tǒng)提供了各種不同形狀的按鈕,客戶端代碼可針對(duì)這些按鈕進(jìn)行編程,用戶可能會(huì)改變需求要求使用不同的按鈕,原始設(shè)計(jì)方案如圖所示:現(xiàn)對(duì)該系統(tǒng)進(jìn)行重構(gòu),使之滿足開閉原則的要求。第四十五頁(yè),共九十七頁(yè)。開閉原則開閉原則實(shí)例實(shí)例解析

第四十六頁(yè),共九十七頁(yè)。里氏代換原則里氏代換原則定義里氏代換原則(LiskovSubstitutionPrinciple,LSP)有兩種定義方式,第一種定義方式相對(duì)嚴(yán)格,其定義如下:如果對(duì)每一個(gè)類型為S的對(duì)象o1,都有類型為T的對(duì)象o2,使得以T定義的所有程序P在所有的對(duì)象o1都代換成o2時(shí),程序P的行為沒有變化,那么類型S是類型T的子類型。第二種更容易理解的定義方式如下:所有引用基類(父類)的地方必須能透明地使用其子類的對(duì)象。第四十七頁(yè),共九十七頁(yè)。里氏代換原則里氏代換原則分析里氏代換原則由2008年圖靈獎(jiǎng)得主、美國(guó)第一位計(jì)算機(jī)科學(xué)女博士、麻省理工學(xué)院BarbaraLiskov教授和卡內(nèi)基-梅隆大學(xué)JeannetteWing教授于1994年提出。芭芭拉·利斯科夫(BarbaraLiskov),美國(guó)計(jì)算機(jī)科學(xué)家,2008年圖靈獎(jiǎng)(計(jì)算機(jī)領(lǐng)域的諾貝爾獎(jiǎng))得主,2004年約翰·馮諾依曼獎(jiǎng)得主。美國(guó)工程院院士,美國(guó)藝術(shù)與科學(xué)院院士,美國(guó)計(jì)算機(jī)協(xié)會(huì)會(huì)士?,F(xiàn)任麻省理工學(xué)院電子電氣與計(jì)算機(jī)科學(xué)系教授。她是美國(guó)第一個(gè)計(jì)算機(jī)科學(xué)女博士,第二位獲得圖靈獎(jiǎng)的女科學(xué)家。第四十八頁(yè),共九十七頁(yè)。里氏代換原則里氏代換原則分析里氏代換原則可以通俗表述為:在軟件中如果能夠使用基類對(duì)象,那么一定能夠使用其子類對(duì)象。把基類都替換成它的子類,程序?qū)⒉粫?huì)產(chǎn)生任何錯(cuò)誤和異常,反過來則不成立,如果一個(gè)軟件實(shí)體使用的是一個(gè)子類的話,那么它不一定能夠使用基類。里氏代換原則是實(shí)現(xiàn)開閉原則的重要方式之一,由于使用基類對(duì)象的地方都可以使用子類對(duì)象,因此在程序中盡量使用基類類型來對(duì)對(duì)象進(jìn)行定義,而在運(yùn)行時(shí)再確定其子類類型,用子類對(duì)象來替換父類對(duì)象。第四十九頁(yè),共九十七頁(yè)。里氏代換原則里氏代換原則分析喜歡動(dòng)物喜歡貓因?yàn)樨埵莿?dòng)物第五十頁(yè),共九十七頁(yè)。里氏代換原則里氏代換原則實(shí)例實(shí)例說明某系統(tǒng)需要實(shí)現(xiàn)對(duì)重要數(shù)據(jù)(如用戶密碼)的加密處理,在數(shù)據(jù)操作類(DataOperator)中需要調(diào)用加密類中定義的加密算法,系統(tǒng)提供了兩個(gè)不同的加密類,CipherA和CipherB,它們實(shí)現(xiàn)不同的加密方法,在DataOperator中可以選擇其中的一個(gè)實(shí)現(xiàn)加密操作。如圖所示:第五十一頁(yè),共九十七頁(yè)。里氏代換原則里氏代換原則實(shí)例實(shí)例說明如果需要更換一個(gè)加密算法類或者增加并使用一個(gè)新的加密算法類,如將CipherA改為CipherB,則需要修改客戶類Client和數(shù)據(jù)操作類DataOperator的源代碼,違背了開閉原則?,F(xiàn)使用里氏代換原則對(duì)其進(jìn)行重構(gòu),使得系統(tǒng)可以靈活擴(kuò)展,符合開閉原則。第五十二頁(yè),共九十七頁(yè)。里氏代換原則里氏代換原則實(shí)例實(shí)例解析第五十三頁(yè),共九十七頁(yè)。依賴倒轉(zhuǎn)原則依賴倒轉(zhuǎn)原則定義依賴倒轉(zhuǎn)原則(DependenceInversionPrinciple,DIP)的定義如下:高層模塊不應(yīng)該依賴低層模塊,它們都應(yīng)該依賴抽象。抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象。另一種表述為:要針對(duì)接口編程,不要針對(duì)實(shí)現(xiàn)編程。第五十四頁(yè),共九十七頁(yè)。依賴倒轉(zhuǎn)原則依賴倒轉(zhuǎn)原則分析依賴倒轉(zhuǎn)原則是RobertC.Martin在1996年為《C++Reporter》所寫的專欄EngineeringNotebook的第三篇,后來加入到他在2002年出版的經(jīng)典著作《AgileSoftwareDevelopment,Principles,Patterns,andPractices》中。第五十五頁(yè),共九十七頁(yè)。依賴倒轉(zhuǎn)原則依賴倒轉(zhuǎn)原則分析簡(jiǎn)單來說,依賴倒轉(zhuǎn)原則就是指:代碼要依賴于抽象的類,而不要依賴于具體的類;要針對(duì)接口或抽象類編程,而不是針對(duì)具體類編程。實(shí)現(xiàn)開閉原則的關(guān)鍵是抽象化,并且從抽象化導(dǎo)出具體化實(shí)現(xiàn),如果說開閉原則是面向?qū)ο笤O(shè)計(jì)的目標(biāo)的話,那么依賴倒轉(zhuǎn)原則就是面向?qū)ο笤O(shè)計(jì)的主要手段。第五十六頁(yè),共九十七頁(yè)。依賴倒轉(zhuǎn)原則依賴倒轉(zhuǎn)原則分析依賴倒轉(zhuǎn)原則的常用實(shí)現(xiàn)方式之一是在代碼中使用抽象類,而將具體類放在配置文件中?!皩⒊橄蠓胚M(jìn)代碼,將細(xì)節(jié)放進(jìn)元數(shù)據(jù)”《程序員修煉之道:從小工到專家》第五十七頁(yè),共九十七頁(yè)。依賴倒轉(zhuǎn)原則依賴倒轉(zhuǎn)原則分析類之間的耦合零耦合關(guān)系具體耦合關(guān)系抽象耦合關(guān)系依賴倒轉(zhuǎn)原則要求客戶端依賴于抽象耦合,以抽象方式耦合是依賴倒轉(zhuǎn)原則的關(guān)鍵。第五十八頁(yè),共九十七頁(yè)。依賴倒轉(zhuǎn)原則依賴倒轉(zhuǎn)原則分析依賴注入第五十九頁(yè),共九十七頁(yè)。依賴倒轉(zhuǎn)原則依賴倒轉(zhuǎn)原則分析依賴注入

構(gòu)造注入(ConstructorInjection):通過構(gòu)造函數(shù)注入實(shí)例變量。設(shè)值注入(SetterInjection):通過Setter方法注入實(shí)例變量。接口注入(InterfaceInjection):通過接口方法注入實(shí)例變量。

第六十頁(yè),共九十七頁(yè)。依賴倒轉(zhuǎn)原則依賴倒轉(zhuǎn)原則分析構(gòu)造注入publicinterfaceAbstractBook{publicvoidview();}publicinterfaceAbstractReader{publicvoidread();}publicclassConcreteBookimplementsAbstractBook{ publicvoidview() { …… }}publicclassConcreteReaderimplementsAbstractReader{ privateAbstractBookbook; publicConcreteReader(AbstractBookbook) { this.book=book; } publicvoidread() { book.view(); }}第六十一頁(yè),共九十七頁(yè)。依賴倒轉(zhuǎn)原則依賴倒轉(zhuǎn)原則分析設(shè)值注入publicinterfaceAbstractBook{publicvoidview();}publicinterfaceAbstractReader{publicvoidsetBook(AbstractBookbook);publicvoidread();}publicclassConcreteBookimplementsAbstractBook{ publicvoidview() { ...... }}publicclassConcreteReaderimplementsAbstractReader{ privateAbstractBookbook; publicvoidsetBook(AbstractBookbook) { this.book=book; } publicvoidread() { book.view(); }}第六十二頁(yè),共九十七頁(yè)。依賴倒轉(zhuǎn)原則依賴倒轉(zhuǎn)原則分析接口注入publicinterfaceAbstractBook{publicvoidview();}publicinterfaceAbstractReader{publicvoidread(AbstractBookbook);}publicclassConcreteBookimplementsAbstractBook{ publicvoidview() { ...... }}publicclassConcreteReaderimplementsAbstractReader{ publicvoidread(AbstractBookbook) { book.view(); }}第六十三頁(yè),共九十七頁(yè)。依賴倒轉(zhuǎn)原則依賴倒轉(zhuǎn)原則實(shí)例實(shí)例說明某系統(tǒng)提供一個(gè)數(shù)據(jù)轉(zhuǎn)換模塊,可以將來自不同數(shù)據(jù)源的數(shù)據(jù)轉(zhuǎn)換成多種格式,如可以轉(zhuǎn)換來自數(shù)據(jù)庫(kù)的數(shù)據(jù)(DatabaseSource)、也可以轉(zhuǎn)換來自文本文件的數(shù)據(jù)(TextSource),轉(zhuǎn)換后的格式可以是xml文件(XMLTransformer)、也可以是xls文件(XLSTransformer)等。第六十四頁(yè),共九十七頁(yè)。依賴倒轉(zhuǎn)原則依賴倒轉(zhuǎn)原則實(shí)例實(shí)例說明由于需求的變化,該系統(tǒng)可能需要增加新的數(shù)據(jù)源或者新的文件格式,每增加一個(gè)新的類型的數(shù)據(jù)源或者新的類型的文件格式,客戶類MainClass都需要修改源代碼,以便使用新的類,違背了開閉原則。現(xiàn)使用依賴倒轉(zhuǎn)原則對(duì)其進(jìn)行重構(gòu)。第六十五頁(yè),共九十七頁(yè)。依賴倒轉(zhuǎn)原則依賴倒轉(zhuǎn)原則實(shí)例實(shí)例解析第六十六頁(yè),共九十七頁(yè)。接口隔離原則接口隔離原則定義接口隔離原則(InterfaceSegregationPrinciple,ISP)的定義如下:客戶端不應(yīng)該依賴那些它不需要的接口。注意,在該定義中的接口指的是所定義的方法。另一種定義方法如下:一旦一個(gè)接口太大,則需要將它分割成一些更細(xì)小的接口,使用該接口的客戶端僅需知道與之相關(guān)的方法即可。第六十七頁(yè),共九十七頁(yè)。接口隔離原則接口隔離原則分析

接口隔離原則是指使用多個(gè)專門的接口,而不使用單一的總接口。每一個(gè)接口應(yīng)該承擔(dān)一種相對(duì)獨(dú)立的角色,不多不少,不干不該干的事,該干的事都要干。(1)一個(gè)接口就只代表一個(gè)角色,每個(gè)角色都有它特定的一個(gè)接口,此時(shí)這個(gè)原則可以叫做“角色隔離原則”。(2)接口僅僅提供客戶端需要的行為,即所需的方法,客戶端不需要的行為則隱藏起來,應(yīng)當(dāng)為客戶端提供盡可能小的單獨(dú)的接口,而不要提供大的總接口。第六十八頁(yè),共九十七頁(yè)。接口隔離原則接口隔離原則分析使用接口隔離原則拆分接口時(shí),首先必須滿足單一職責(zé)原則,將一組相關(guān)的操作定義在一個(gè)接口中,且在滿足高內(nèi)聚的前提下,接口中的方法越少越好??梢栽谶M(jìn)行系統(tǒng)設(shè)計(jì)時(shí)采用定制服務(wù)的方式,即為不同的客戶端提供寬窄不同的接口,只提供用戶需要的行為,而隱藏用戶不需要的行為。第六十九頁(yè),共九十七頁(yè)。接口隔離原則接口隔離原則實(shí)例實(shí)例說明下圖展示了一個(gè)擁有多個(gè)客戶類的系統(tǒng),在系統(tǒng)中定義了一個(gè)巨大的接口AbstractService來服務(wù)所有的客戶類??梢允褂媒涌诟綦x原則對(duì)其進(jìn)行重構(gòu)。第七十頁(yè),共九十七頁(yè)。接口隔離原則接口隔離原則實(shí)例實(shí)例解析第七十一頁(yè),共九十七頁(yè)。合成復(fù)用原則合成復(fù)用原則定義合成復(fù)用原則(CompositeReusePrinciple,CRP)又稱為組合/聚合復(fù)用原則(Composition/AggregateReusePrinciple,CARP),其定義如下:盡量使用對(duì)象組合,而不是繼承來達(dá)到復(fù)用的目的。第七十二頁(yè),共九十七頁(yè)。合成復(fù)用原則合成復(fù)用原則分析合成復(fù)用原則就是指在一個(gè)新的對(duì)象里通過關(guān)聯(lián)關(guān)系(包括組合關(guān)系和聚合關(guān)系)來使用一些已有的對(duì)象,使之成為新對(duì)象的一部分;新對(duì)象通過委派調(diào)用已有對(duì)象的方法達(dá)到復(fù)用其已有功能的目的。簡(jiǎn)言之:要盡量使用組合/聚合關(guān)系,少用繼承。第七十三頁(yè),共九十七頁(yè)。合成復(fù)用原則合成復(fù)用原則分析在面向?qū)ο笤O(shè)計(jì)中,可以通過兩種基本方法在不同的環(huán)境中復(fù)用已有的設(shè)計(jì)和實(shí)現(xiàn),即通過組合/聚合關(guān)系或通過繼承。繼承復(fù)用:實(shí)現(xiàn)簡(jiǎn)單,易于擴(kuò)展。破壞系統(tǒng)的封裝性,從基類繼承而來的實(shí)現(xiàn)是靜態(tài)的,不可能在運(yùn)行時(shí)發(fā)生改變,沒有足夠的靈活性;只能在有限的環(huán)境中使用。(“白箱”復(fù)用)組合/聚合復(fù)用:耦合度相對(duì)較低,選擇性地調(diào)用成員對(duì)象的操作;可以在運(yùn)行時(shí)動(dòng)態(tài)進(jìn)行。(“黑箱”復(fù)用)第七十四頁(yè),共九十七頁(yè)。合成復(fù)用原則合成復(fù)用原則分析組合/聚合可以使系統(tǒng)更加靈活,類與類之間的耦合度降低,一個(gè)類的變化對(duì)其他類造成的影響相對(duì)較少,因此一般首選使用組合/聚合來實(shí)現(xiàn)復(fù)用;其次才考慮繼承,在使用繼承時(shí),需要嚴(yán)格遵循里氏代換原則,有效使用繼承會(huì)有助于對(duì)問題的理解,降低復(fù)雜度,而濫用繼承反而會(huì)增加系統(tǒng)構(gòu)建和維護(hù)的難度以及系統(tǒng)的復(fù)雜度,因此需要慎重使用繼承復(fù)用。第七十五頁(yè),共九十七頁(yè)。合成復(fù)用原則合成復(fù)用原則實(shí)例實(shí)例說明某教學(xué)管理系統(tǒng)部分?jǐn)?shù)據(jù)庫(kù)訪問類設(shè)計(jì)如圖所示:第七十六頁(yè),共九十七頁(yè)。合成復(fù)用原則合成復(fù)用原則實(shí)例實(shí)例說明如果需要更換數(shù)據(jù)庫(kù)連接方式,如原來采用JDBC連接數(shù)據(jù)庫(kù),現(xiàn)在采用數(shù)據(jù)庫(kù)連接池連接,則需要修改DBUtil類源代碼。如果StudentDAO采用JDBC連接,但是TeacherDAO采用連接池連接,則需要增加一個(gè)新的DBUtil類,并修改StudentDAO或TeacherDAO的源代碼,使之繼承新的數(shù)據(jù)庫(kù)連接類,這將違背開閉原則,系統(tǒng)擴(kuò)展性較差?,F(xiàn)使用合成復(fù)用原則對(duì)其進(jìn)行重構(gòu)。第七十七頁(yè),共九十七頁(yè)。合成復(fù)用原則合成復(fù)用原則實(shí)例實(shí)例解析

第七十八頁(yè),共九十七頁(yè)。迪米特法則迪米特法則定義迪米特法則(LawofDemeter,LoD)又稱為最少知識(shí)原則(LeastKnowledgePrinciple,LKP),它有多種定義方法,其中幾種典型定義如下:(1)不要和“陌生人”說話。(2)只與你的直接朋友通信。(3)每一個(gè)軟件單位對(duì)其他的單位都只有最少的知識(shí),而且局限于那些與本單位密切相關(guān)的軟件單位。第七十九頁(yè),共九十七頁(yè)。迪米特法則迪米特法則分析迪米特法則來自于1987年秋美國(guó)東北大學(xué)(NortheasternUniversity)一個(gè)名為“Demeter”的研究項(xiàng)目。簡(jiǎn)單來說,迪米特法則就是指一個(gè)軟件實(shí)體應(yīng)當(dāng)盡可能少的與其他實(shí)體發(fā)生相互作用。這樣,當(dāng)一個(gè)模塊修改時(shí),就會(huì)盡量少的影響其他的模塊,擴(kuò)展會(huì)相對(duì)容易,這是對(duì)軟件實(shí)體之間通信的限制,它要求限制軟件實(shí)體之間通信的寬度和深度。第八十頁(yè),共九十七頁(yè)。迪米特法則迪米特法則分析在迪米特法則中,對(duì)于一個(gè)對(duì)象,其朋友包括以下幾類:(1)當(dāng)前對(duì)象本身(this);(2)以參數(shù)形式傳入到當(dāng)前對(duì)象方法中的對(duì)象;(3)當(dāng)前對(duì)象的成員對(duì)象;(4)如果當(dāng)前對(duì)象的成員對(duì)象是一個(gè)集合,那么集合中的元素也都是朋友;(5)當(dāng)前對(duì)象所創(chuàng)建的對(duì)象。任何一個(gè)對(duì)象,如果滿足上面的條件之一,就是當(dāng)前對(duì)象的“朋友”,否則就是“陌生人”。第八十一頁(yè),共九十七頁(yè)。迪米特法則迪米特法則分析迪米特法則可分為狹義法則和廣義法則。在狹義的迪米特法則中,如果兩個(gè)類之間不必彼此直接通信,那么這兩個(gè)類就不應(yīng)當(dāng)發(fā)生直接的相互作用,如果其中的一個(gè)類需要調(diào)用另一個(gè)類的某一個(gè)方法的話,可以通過第三者轉(zhuǎn)發(fā)這個(gè)調(diào)用。第八十二頁(yè),共九十七頁(yè)。迪米特法則迪米特法則分析狹義的迪米特法則:可以降低類之間的耦合,但是會(huì)在系統(tǒng)中增加大量的小方法并散落在系統(tǒng)的各個(gè)角落,它可以使一個(gè)系統(tǒng)的局部設(shè)計(jì)簡(jiǎn)化,因?yàn)槊恳粋€(gè)局部都不會(huì)和遠(yuǎn)距離的對(duì)象有直接的關(guān)聯(lián),但是也會(huì)造成系統(tǒng)的不同模塊之間的通信效率降低,使得系統(tǒng)的不同模塊之間不容易協(xié)調(diào)。廣義的迪米特法則:指對(duì)對(duì)象之間的信息流量、流向以及信息的影響的控制,主要是對(duì)信息隱藏的控制。信息的隱藏可以使各個(gè)子系統(tǒng)之間脫耦,從而允許它們獨(dú)立地被開發(fā)、優(yōu)化、使用和修改,同時(shí)可以促進(jìn)軟件的復(fù)用,由于每一個(gè)模塊都不依賴于其他模塊而存在,因此每一個(gè)模塊都可以獨(dú)立地在其他的地方使用。一個(gè)系統(tǒng)的規(guī)模越大,信息的隱藏就越重要,而信息隱藏的重要性也就越明顯。第八十三頁(yè),共九十七頁(yè)。迪米特法則迪米特法則分析迪米特法則的主要用途在于控制信息的過載:在類的劃分上,應(yīng)當(dāng)盡量創(chuàng)建松耦合的類,類之間的耦合度越低,就越有利于復(fù)用,一個(gè)處在松耦合中的類一旦被修改,不會(huì)對(duì)關(guān)聯(lián)的類造成太大波及;在類的結(jié)構(gòu)設(shè)計(jì)上,每一個(gè)類都應(yīng)當(dāng)盡量降低其成員變量和成員函數(shù)的訪問權(quán)限;在類的設(shè)計(jì)上,只要有可能,一個(gè)類型應(yīng)當(dāng)設(shè)計(jì)成不變類;在對(duì)其他類的引用上,一個(gè)對(duì)象對(duì)其他對(duì)象的引用應(yīng)當(dāng)降到最低。第八十四頁(yè),共九十七頁(yè)。迪米特法則迪米特法則實(shí)例實(shí)例說明某系統(tǒng)界面類(如Form1、Form2等類)與數(shù)據(jù)訪問類(如DAO1、DAO2等類)之間的調(diào)用關(guān)系較為復(fù)雜,如圖所示:第八十五頁(yè),共九十七頁(yè)。迪米特法則迪米特法則實(shí)例實(shí)例解析第八十六頁(yè),共九十七頁(yè)。小結(jié)對(duì)于面向?qū)ο蟮能浖到y(tǒng)設(shè)計(jì)來說,在支持可維護(hù)性的同時(shí),需要提高系統(tǒng)的可復(fù)用性。軟件的復(fù)用可以提高軟件的開發(fā)效率,提高軟件質(zhì)量,節(jié)約開發(fā)成本,恰當(dāng)?shù)膹?fù)用還可以改善系統(tǒng)的可維護(hù)性。單一職責(zé)原則要求在軟件系統(tǒng)中,一個(gè)類只負(fù)責(zé)一個(gè)功能領(lǐng)域中的相應(yīng)職責(zé)。開閉原則要求一個(gè)軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉,即在不修改源代碼的基礎(chǔ)上擴(kuò)展一個(gè)系統(tǒng)的行為。里氏代換原則可以通俗表述為在軟件中如果能夠使用基類對(duì)象,那么一定能夠使用其子類對(duì)象。第八十七頁(yè),共九十七頁(yè)。小結(jié)依賴倒轉(zhuǎn)原則要求抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象;要針對(duì)接口編程,不要針對(duì)實(shí)現(xiàn)編程。接口隔離原則要求客戶端不應(yīng)該依賴那些它不需要的接口,即將一些大的接口細(xì)化成一些小的接口供客戶端使用。合成復(fù)用原則要求復(fù)用時(shí)盡量使用對(duì)象組合,而不使用繼承。迪米特法則要求一個(gè)軟件實(shí)體應(yīng)當(dāng)盡可能少的與其他實(shí)體發(fā)生相互作用。第八十八頁(yè),共九十七頁(yè)。一些基本的設(shè)計(jì)模式AbstractFactory:提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴對(duì)象的接口,而無需指定它們具體的類。Adapter:將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作。Bridge:將抽象部分與它的實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立地變化。Builder:將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。ChainofResponsibility:為解除請(qǐng)求的發(fā)送者和接收者之間耦合,而使多個(gè)對(duì)象都有機(jī)會(huì)處理這個(gè)請(qǐng)求。將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求,直到有一個(gè)對(duì)象處理它。Command:將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而使你可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化;對(duì)請(qǐng)求排隊(duì)或記錄請(qǐng)求日志,以及支持可取消的操作。第八十九頁(yè),共九十七頁(yè)。Composite:將對(duì)象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)。它使得客戶對(duì)單個(gè)對(duì)象和復(fù)合對(duì)象的使用具有一致性。Decorator:動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。就擴(kuò)展功能而言,它比生成子類方式更為靈活。Fac

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論