《軟件工程-理論、方法與實(shí)踐》課件第11章_第1頁
《軟件工程-理論、方法與實(shí)踐》課件第11章_第2頁
《軟件工程-理論、方法與實(shí)踐》課件第11章_第3頁
《軟件工程-理論、方法與實(shí)踐》課件第11章_第4頁
《軟件工程-理論、方法與實(shí)踐》課件第11章_第5頁
已閱讀5頁,還剩61頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第11章軟件實(shí)現(xiàn)11.1程序設(shè)計(jì)語言11.2編碼風(fēng)格11.3程序的效率本章小結(jié)習(xí)題

11.1程序設(shè)計(jì)語言

程序設(shè)計(jì)語言一直在不斷地演化和演變,其發(fā)展經(jīng)歷了從機(jī)器語言到高級語言的過程。

計(jì)算機(jī)問世初期,程序設(shè)計(jì)語言是與計(jì)算機(jī)硬件緊密相關(guān)的機(jī)器語言和匯編語言,編寫這種語言程序難度大、效率低,不易于理解且難以調(diào)試。11.1.1程序設(shè)計(jì)語言的特性

特定的程序設(shè)計(jì)語言有一些特定的限制,它們影響著程序員描述和處理問題的方式。程序設(shè)計(jì)語言應(yīng)著重考慮程序員易學(xué)易用、不易出錯(cuò),因此程序設(shè)計(jì)語言須考慮下列特性:

(1)一致性(Uniforminy)。

(2)二義性(Ambiguity)。

(3)緊致性(Compactness)。

(4)局部性(Locality)。

(5)線性(Linearity)。11.1.2程序設(shè)計(jì)語言的選擇

總的來說,程序設(shè)計(jì)語言的選擇需要結(jié)合具體問題進(jìn)行分析評價(jià),下面給出一些可供參考的實(shí)用標(biāo)準(zhǔn):

(1)系統(tǒng)用戶的要求。

(2)程序員的知識。

(3)軟件可移植性要求。

(4)軟件的應(yīng)用領(lǐng)域。目前面向?qū)ο蠓椒ㄊ擒浖_發(fā)的主流方法,因此面向?qū)ο笳Z言的選擇問題更受關(guān)注。開發(fā)人員在選擇面向?qū)ο笳Z言時(shí),應(yīng)該著重考慮以下一些實(shí)際因素:

(1)將來能否占主導(dǎo)地位。

(2)可復(fù)用性。

(3)類庫和開發(fā)環(huán)境。

(4)其他因素。

11.2編碼風(fēng)格

11.2.1命名

程序設(shè)計(jì)過程要涉及到對變量、常量、函數(shù)、類、對象等編程元素進(jìn)行命名。一個(gè)變量的作用域越大,它的名字所攜帶的信息就應(yīng)該越多。下面是一些通用的規(guī)則:

(1)標(biāo)識符的命名應(yīng)當(dāng)直觀,可以望文知義,最好采用英文單詞或其組合。

(2)標(biāo)識符的長度應(yīng)當(dāng)符合“最小長度下的最大信息”原則,過長的英文單詞應(yīng)該采用一些通用而合理的縮寫或者應(yīng)用領(lǐng)域?qū)I(yè)術(shù)語的縮寫。

(3)程序中不要出現(xiàn)僅依靠大小寫來區(qū)分的相似標(biāo)識符。

(4)程序中不要出現(xiàn)局部變量和全局變量同名的現(xiàn)象,以免引起誤解。

(5)變量名應(yīng)當(dāng)使用“名詞”或者“形容詞?+?名詞”的形式。

(6)函數(shù)名應(yīng)當(dāng)使用“動詞”或者“動詞?+?名詞”的形式。例11.1Java命名實(shí)例。

packageorg.jr.jzj.editor;

importjava.awt.*;

importjavax.swing.*;

publicclassLineNumberextendsJComponent{

privatefinalstaticColorDEFAULT_BACKGROUND=Color.white;

privatefinalstaticColorDEFAULT_FOREGROUND=newColor(153,153,204);

privatefinalstaticColorDEFAULT_LINECLR=newColor(192,192,192);

privatefinalstaticFontDEFAULT_FONT=newFont("SansSerif",Font.PLAIN,12);

privatefinalstaticintHEIGHT=Integer.MAX_VALUE-1000000;

privatefinalstaticintMARGIN=5;

privateFontMetricsfontMetrics;

privateintlineHeight;

privateintcurrentRowWidth;

privateJComponentcomponent;

privateintcomponentFontHeight;

privateintcomponentFontAscent;

publicLineNumber(JComponentcomponent){

if(component==null){

setBackground(DEFAULT_BACKGROUND);

setForeground(DEFAULT_FOREGROUND);

setFont(DEFAULT_FONT);

ponent=this;

}

else{

setBackground(DEFAULT_BACKGROUND);

setForeground(component.getForeground());

setFont(component.getFont());

ponent=component;

}

componentFontHeight=component.getFontMetrics(component.getFont()).getHeight();

componentFontAscent=component.getFontMetrics(component.getFont()).getAscent();

setPreferredWidth(9999);

this.setBorder(BorderFactory.createLineBorder(DEFAULT_LINECLR,1));

}

publicvoidsetPreferredWidth(introw){

intwidth=fontMetrics.stringWidth(String.valueOf(row));

if(currentRowWidth<width){

currentRowWidth=width;

setPreferredSize(newDimension(2*MARGIN+width,HEIGHT));

}

}

publicvoidsetFont(Fontfont){

super.setFont(font);

fontMetrics=getFontMetrics(getFont());

}

publicintgetLineHeight(){

if(lineHeight==0){

returncomponentFontHeight;

}

else{

returnlineHeight;

}

}

publicvoidsetLineHeight(intlineHeight){

if(lineHeight>0){

this.lineHeight=lineHeight;

}

}

publicintgetStartOffset(){

returncomponent.getInsets().top+componentFontAscent;

}

publicvoidpaintComponent(Graphicsg){

intlineHeight=getLineHeight();

intstartOffset=getStartOffset();

RectangledrawHere=g.getClipBounds();

g.setColor(getBackground());

g.fillRect(drawHere.x,drawHere.y,drawHere.width,drawHere.height);

g.setColor(getForeground());

intstartLineNumber=(drawHere.y/lineHeight)+1;

intendLineNumber=startLineNumber+(drawHere.height/lineHeight);

intstart=(drawHere.y/lineHeight)*lineHeight+startOffset;

for(inti=startLineNumber;i<=endLineNumber;i++){

StringlineNumber=String.valueOf(i);

intwidth=fontMetrics.stringWidth(lineNumber);

g.drawString(lineNumber,MARGIN+currentRowWidth-width,start);

start+=lineHeight;

}

setPreferredWidth(endLineNumber);

}

}11.2.2注釋

注釋是幫助閱讀和理解程序的有效手段,用自然語言或偽碼描述。注釋說明了程序的功能,特別是在維護(hù)階段,對理解程序提供了明確的指導(dǎo)。書寫注釋應(yīng)該注意以下問題:

(1)程序中的注釋不宜過多,否則會使人眼花繚亂。

(2)不必要注釋含義已經(jīng)十分清楚的代碼。

(3)修改代碼時(shí)應(yīng)該同時(shí)修改注釋,以保證代碼和注釋的一致性。

(4)注釋應(yīng)該準(zhǔn)確易懂,防止出現(xiàn)二義性,錯(cuò)誤的注釋不但無益而且有害。

(5)注釋的位置應(yīng)該與被描述的代碼相鄰,應(yīng)該寫在程序代碼的上方并且和代碼左對齊。

(6)變量定義和分支語句必須寫注釋,因?yàn)檫@些語句往往是程序某一特定功能的關(guān)鍵。例11.2Java注釋實(shí)例。

packagecom.lowagie.text;

import.MalformedURLException;

/**

*A<CODE>Watermark</CODE>isagraphicelement(GIForJPEG)

*thatisshownonacertainpositiononeachpage.

*

*@see Element

*@see Jpeg

*@see Gif

*@see Png

*/publicclassWatermarkextendsImageimplementsElement{

//membervariables

/**Thisistheoffsetinx-directionoftheWatermark.*/

privatefloatoffsetX=0;

/**Thisistheoffsetiny-directionoftheWatermark.*/

privatefloatoffsetY=0;

//Constructors

/**

*Constructsa<CODE>Watermark</CODE>-object,usingan<CODE>Image</CODE>.

*

*@param image an<CODE>Image</CODE>-object

*@param offsetX theoffsetinx-direction

*@param offsetY theoffsetiny-direction

*/publicWatermark(Imageimage,floatoffsetX,floatoffsetY)throwsMalformedURLException{

super(image);

this.offsetX=offsetX;

this.offsetY=offsetY;

}

//implementationoftheElementinterface

/**

*Getsthetypeofthetextelement.

*

*@return atype

*/

publicinttype(){

returntype;

}

//methodstoretrieveinformation

/**

*Returnstheoffsetinxdirection.

*

*@return anoffset

*/

publicfloatoffsetX(){

returnoffsetX;

}

/**

*Returnstheoffsetinydirection.

*

*@return anoffset

*/

publicfloatoffsetY(){

returnoffsetY;

}

}11.2.3源代碼版式

1.適當(dāng)?shù)目招?/p>

在源代碼中適度地使用空行可以使程序的結(jié)構(gòu)更加清晰,空行分隔一般出現(xiàn)在:

●源文件中的各個(gè)節(jié)之間。

●源文件中的類與類、類與接口之間。

●方法定義之間。

●局部變量定義和第一個(gè)語句之間。

●注釋塊或注釋行之前。

●語句的不同邏輯分段之間。

2.代碼行及行內(nèi)空格

●一行代碼只寫一條語句,避免使用復(fù)雜的語句行。

●行內(nèi)空格一般出現(xiàn)在關(guān)鍵字和括號之間、參數(shù)列表中逗號之后、二元運(yùn)算符之間、語句中的表達(dá)式之間以及賦值符號之后。

例11.3

代碼行風(fēng)格實(shí)例及其修改結(jié)果。

(1)變量定義。

避免使用:

intwidth,height; //寬度和高度

應(yīng)該采用:

intwidth=10;

intheight=10;(2)運(yùn)算表達(dá)式。

避免使用:

x=a+b;a+=c+d;

應(yīng)該采用:

x=a+b;

a+=c+d;(3)其他語句。

避免使用:

prints("sizeis"+foo+"\n");

應(yīng)該采用:

prints("sizeis"+foo+"\n"); //增加了空格

3.分行、對齊與縮進(jìn)

●代碼行最大長度最好控制在70或80個(gè)字符之內(nèi),超過這個(gè)范圍應(yīng)當(dāng)分成多行。

●分行應(yīng)在逗號之后、操作符之前。

●長表達(dá)式應(yīng)在低優(yōu)先級的操作符處拆分成新行,操作符放在新行之首。

●拆分出的新行要進(jìn)行適當(dāng)?shù)目s進(jìn),建議采用8個(gè)空格縮進(jìn),使排版整齊,語句可讀。

例11.4

分行、對齊與縮進(jìn)的實(shí)例。

(1)函數(shù)參數(shù)列表分行。

myMethod(longExpression1,longExpression2,longExpression3,

longExpression4,longExpression5);

(2)運(yùn)算表達(dá)式分行。

避免使用:

longName1=longName2*(longName3+longName4

-longName5)+4*longName6;

應(yīng)該采用:

longName1=longName2*(longName3+longName4-longName5)+4*longName6;

(3)條件表達(dá)式分行。

避免使用:

if((condition1&&condition2)||(condition3&&condition4)||!(condition5&&condition6))

{

doSomethingAboutIt();

}應(yīng)該采用:

if((condition1&&condition2)

||(condition3&&condition4) //分行和縮進(jìn)

||!(condition5&&condition6)){

doSomethingAboutIt();

}也可以采用:

if((condition1&&condition2)||(condition3&&condition4)

||!(condition5&&condition6)){

doSomethingAboutIt();

}11.2.4異常處理

在C++語言中,catch語句可以捕獲各種類型的異常。然而,在處理異常的過程中,人們往往會忘記對拋出的異常對象的內(nèi)存釋放。下面的程序使用了C++?的異常處理機(jī)制,但是這個(gè)程序中存在一個(gè)錯(cuò)誤,有可能造成內(nèi)存泄漏。classmyException{

public:

interrorInfo;

myException(interrorInfo)

{

this->errorInfo=errorInfo;

}

};voidShowException(intcode)

{

if(code<0)

thrownewmyException(code);

}

intmain()

{

intcode=-100;

try

{

ShowException(code);

}

catch(myException*e)

{

cout>>“錯(cuò)誤代瑪為:”>>e->errorInfo;

}

}在C++語言中,異常處理機(jī)制類似于goto語句的執(zhí)行原理。上述程序中新創(chuàng)建的異常對象指針作為參數(shù)被傳進(jìn)了catch函數(shù),而catch函數(shù)可以看成是一個(gè)不再返回調(diào)用點(diǎn)的函數(shù),因此當(dāng)處理過程結(jié)束后,程序并沒有釋放這個(gè)新對象占用的空間,這樣在某些關(guān)鍵性的應(yīng)用中可能會導(dǎo)致系統(tǒng)內(nèi)存不足。為了避免上述問題的出現(xiàn),應(yīng)該在catch塊的最后加上delete語句,具體修改如下:

catch(myException*e)

{

cout>>“錯(cuò)誤代瑪為:”>>e->errorInfo;

deletep;

}

異常處理機(jī)制相當(dāng)有用,但同時(shí)也容易被誤用而導(dǎo)致代碼結(jié)構(gòu)混亂。在使用異常處理的過程中,必須十分清楚在沒有異常拋出、異常拋出時(shí)和異常處理后的程序執(zhí)行流程,把握異常處理中的跳轉(zhuǎn)和嵌套機(jī)制,并注意異常處理時(shí)存在的問題。

11.3程?序?的?效?率

程序的效率是指程序執(zhí)行速度的快慢和程序占用存儲空間的大小。效率要求實(shí)際上就是性能要求,對效率追求應(yīng)取決于在需求分析階段所確定的效率方面的要求;好的設(shè)計(jì)也可以提高程序效率,即在設(shè)計(jì)階段要設(shè)計(jì)出高效率的程序結(jié)構(gòu);編碼階段則是提高程序效率的最后時(shí)機(jī)。因此,編碼過程中,在不影響程序的清晰性和可讀性的前提下,必須考慮如何提高程序效率。下面從三個(gè)方面來討論程序的效率問題。

1.程序運(yùn)行時(shí)間

設(shè)計(jì)階段所確定的算法的效率決定了源程序的效率;在編碼階段,編碼風(fēng)格也影響著程序的執(zhí)行速度和存儲器要求。因此,在編碼階段,將設(shè)計(jì)的結(jié)果轉(zhuǎn)化成程序代碼時(shí),應(yīng)遵循以下原則:

(1)編碼前先化簡算術(shù)表達(dá)式和邏輯表達(dá)式。

(2)仔細(xì)檢查算法中嵌套的循環(huán),以確定是否有語句可以從內(nèi)層向外移。

(3)盡量不使用多維數(shù)組。

(4)盡量不使用指針和復(fù)雜的表。

(5)使用執(zhí)行時(shí)間短的算術(shù)運(yùn)算。

(6)在表達(dá)式中盡量避免出現(xiàn)不同的數(shù)據(jù)類型。

(7)盡量使用整數(shù)算術(shù)表達(dá)式和布爾表達(dá)式。

(8)選用等效的高效率算法。

對某些效率起決定性因素的系統(tǒng),盡量使用具有“優(yōu)化”功能的編譯程序,以自動生成高效的目標(biāo)代碼。下面程序中的lowerStr函數(shù)是將字符串中所有大寫字母變成小寫字母,而main函數(shù)中含有測量并顯示運(yùn)行時(shí)間的功能。其中一些語句會對程序的執(zhí)行速度產(chǎn)生影響。

#include<stdio.h>

#include<ctype.h>

#include<string.h>

#include<time.h>voidlowserStr(char*str)

{

char*p;

for(p=str;p<str+strlen(str);p++){

if(isupper(*p))

*p=tolower(*p)

}

}intmain()

{

charmsg[255]="SomeoftheLETTERSareCapitals.\n";

intcount=0;

printf("請輸入執(zhí)行次數(shù)");

scanf("%d",&count);

clock_ttimeBegin,timeEnd; timeBegin=clock();

for(inti=0;i<count;i++)

lowerStr(msg);

timeEnd=clock();

printf("花費(fèi)時(shí)間:%.3f秒\n",(timeEnd-timeBegin)/CLOCKS_PER_SEC);

return0;

}可以看出上述代碼中存在問題,在lowerStr函數(shù)的for循環(huán)條件表達(dá)式中包含strLen函數(shù),這種寫法會造成每次循環(huán)時(shí)都要重復(fù)調(diào)用該函數(shù),從而使程序的運(yùn)行效率大大降低。由于在循環(huán)過程中,strLen函數(shù)的計(jì)算結(jié)果是不變的,因此可以提前將字符串的長度計(jì)算出來并賦給一個(gè)變量,然后在循環(huán)中使用該變量即可。根據(jù)上面的分析,lowerStr函數(shù)的修改結(jié)果如下:

voidlowserStr(char*str)

{

char*p;

intlen=strLen(str);

for(p=str;p<str+len;p++){

if(isupper(*p))

*p=tolower(*p)

}

}使用了優(yōu)化方法后,讓該程序循環(huán)執(zhí)行10000次,結(jié)果顯示未優(yōu)化的程序執(zhí)行時(shí)間為0.144?s,優(yōu)化后的執(zhí)行時(shí)間為0.092?s,速度大約提高36%。

編寫程序時(shí),不要費(fèi)力地追求編寫快速的程序,應(yīng)該努力編寫好的程序。具備良好的編程習(xí)慣,程序效率會自然隨之而來。如果發(fā)現(xiàn)編寫的程序速度確實(shí)比較慢,可以在性能分析器的幫助下找到問題的根源,然后設(shè)法優(yōu)化系統(tǒng)中相關(guān)的部分。

2.存儲器效率

在微型計(jì)算機(jī)中,對軟件設(shè)計(jì)和編碼的最大制約是存儲限制,即要求使用最少的存儲單元。因此,要選用有緊縮存儲器特性的編譯程序,生成較短目標(biāo)代碼,在必要時(shí)可以使用匯編語言。在大中型計(jì)算機(jī)系統(tǒng)中,對內(nèi)存管理采取的是基于操作系統(tǒng)的分頁功能的虛擬存儲管理。因此,存儲限制不再是主要問題,不必強(qiáng)調(diào)所使用的空間越少越好,存儲的效率直接與操作系統(tǒng)的分頁功能有關(guān)。一般來說,使用能保持功能域結(jié)構(gòu)化的控制結(jié)構(gòu),以減少頁面調(diào)度,減少內(nèi)外存之間的交換,是提高效率的好方法。

提高程序執(zhí)行效率的技術(shù)也能提高存儲器效率。提高存儲器效率的關(guān)鍵在于程序的簡單性。重復(fù)使用同一個(gè)對象,而不是每次

溫馨提示

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

最新文檔

評論

0/150

提交評論