程式碼維護:改進程式碼的一些方法 (轉)

worldblog發表於2007-12-12
程式碼維護:改進程式碼的一些方法 (轉)[@more@]

程式碼維護:改進程式碼的一些方法:namespace prefix = o ns = "urn:schemas--com::office" />

0 引言

應用的整個生命週期的維護通常都被低估了。然而,維護毫無疑問是花費最多、也是最難的階段。因此,初始開發階段的程式碼質量直接影響維護的成本。下面一些數字說明了這一點:

·  一個專案的平均壽命是4到5年,開發階段大約是一年。

·  在此階段,40% 到50%的程式碼都需要修改,或者是糾錯,或者是。

·  維護階段修改一行程式碼的成本是初始開發階段的2到3倍。

這些數字表明:

·  程式碼必須清晰而且有正確的文字註釋,這樣在4、5年後仍能理解,甚至當程式碼的開發人員都不在時。

·  程式碼必須可更新而且有恰當的結構以面對將來的變化。

·  專案中的錯誤必須儘可能早地檢查出來,以限制將來產生影響的成本。

我們將會看見如何遵循一些簡單的規則,開發人員透過限制成本和風險來促進維護工作。為了提供一個具體的例項,我們將改進以下的程式碼,採用的是Powerbuilder中的powerscript語言的程式碼,這些程式碼是從資料視窗的itemchanged 事件中提取的。

long a

if dwo.name = "amount" THEN

  IF dw_1.getitemnumber (row, "type") = 5 OR dw_1.getitemnumber (row, "type") = 6 THEN

  dec b

  for a = 1 to  dw_1.rowcount ()

  if dw_1.getitemnumber (a, "type") = 5 or dw_1.getitemnumber (a, "type") = 6 &

and a <> row THEN

  b += dw_1.getitemnumber (a, "amount")

  END if

  next

  if dec (data) + b > 450000 THEN

  messagebox ("Error","the total amount of this sales order is too big")

  return 1

  END IF

  END IF

END IF

if dwo.name = "type" then

  // 如果資料視窗列為"type",則...

END IF

if dwo.name = "amount" then

  // 如果資料視窗物件列為"amount",則...

END IF

1 增加程式碼的易理解性

你研究過多少次別人的程式碼(甚至你自己寫的程式碼),抱怨過它多麼難於理解?儘管很容易判斷程式碼是否易讀,但更難說明其原因。這裡有一些規則,如果遵循的話,將會保證最小的易讀性。

1.1 正確命名程式碼元素

  需要命名正確的主要因素是物件,和變數。命名正確意味著名稱必須代表專案的主要屬性。換句話來說,名稱必須清楚地描述物件能做什麼,如何使用。

  舉例來說,如果變數命名為a,它並不代表它用來做什麼,資料型別是什麼。為了達到這個目的,必須要搜尋變數的定義,分析程式碼以學會如何使用。讓我們重新考慮這個變數,命名為ll_rowcount,這樣,甚至沒有上下文的聯絡,我們也可以得知它是處理一個區域性變數,長整型long,用來儲存記錄數目。如果遵守公司的命名規則,用常規語言來分配名稱,就能夠大大增強程式碼的易讀性。

1.2 定義和複雜必須加以註解

為了加強程式碼的可理解性,必須給程式碼增加註解。有些開發人員完全不新增註解,而有些則每行加以註解。照我看來,我們必須在這兩種極限情況下選擇一個平衡狀態。實際上,註解是有成本的,很難保持註解與修改後的程式碼保持一致(因為編譯時註解並沒有被檢查)。這就是我為什麼認為註解只應該加在能夠提高程式碼可理解性的地方:

·  變數定義,如果它們的名稱不能充分描述它們的用途;

·  不能想當然的表示式(如數學公式、複雜條件等等)。

1.3 複雜條件必須易於理解

如果條件很複雜,在閱讀的時候就很難把握意思。於是就有必要儘可能地使它易於閱讀,所以就要儘量避免使用函式、用固定型別的變數來替換不明確的值。

示例:

將程式碼

long a

if dw_1.getitemnumber (row, "type") = 5 or dw_1.getitemnumber (row, "type") = 6 AND a <> row

  ...

end if

改為:

li_producttype = dw_1.getitemnumber (row, "type")

IF li_producttype = BOOK OR li_producttype = VO AND ll_currentrow <> row THEN

  …

END IF

1.4 區域性變數必須在程式碼的開頭就加以定義

PowerBuilder的並不要求變數定義的位置,於是,就可以在程式碼的開頭定義所有的變數。這在我們尋找定義時,大大簡化了搜尋過程。

2 程式碼的規劃和文件的規劃一樣重要

這個規則能夠很好地實施,因為PowerBuilder程式碼編輯器透過提供自動縮排和顏色指示大大簡化了這項任務。不過仍然建議你重新閱讀你的程式碼,試著改進其規劃

·  配合自動縮排原則

·  正確定義變數

·  在的每個部分之間留下一個空行

·  如果一行指令太長而不能在一行中閱讀,則開始新的一行

如果我們應用這些原則到示例程式碼中,將會得到以下程式碼:

long :  ll_currentrow, ll_rowcount

int li_producttype

dec ldc_total

constant int   BOOK = 5, VIDEO = 6

constant dec  MAXAMOUNT = 450000  // 指出books和video的最大數目

CHOOSE CASE dwo.name

  CASE "amount"

 

  // 檢查books和video的總數沒有超過最大數目

  //======================================================================

  li_producttype = dw_1.getitemnumber (row, "type")

  IF li_producttype = BOOK OR li_producttype = VIDEO THEN

  // 不考慮當前行資料計算銷售訂單的數目

  //=================================================================

  ll_rowcount = dw_1.rowcount ()

  FOR ll_currentrow = 1 TO  ll_rowcount

  ll_producttype = dw_1.getitemnumber (ll_currentrow , "type")

  IF  li_producttype = BOOK OR li_producttype = VIDEO AND &

  ll_currentrow <> row THEN

  ldc_total += dw_1.getitemnumber (ll_currentrow, "amount")

  END IF

  NEXT

 

  IF (DEC (data) + ldc_total) > MAXAMOUNT THEN

  messagebox ("Error", "the total amount for books and video is too big")

  return 1

  END IF

  END IF

 

  // 如果資料視窗物件列為"amount",則...

 

  CASE "type"

  // 如果資料視窗物件列為"type",則...  

END CHOOSE

3 程式碼文件化

文件使我們不需要鑽研程式碼,就可以輕鬆地理解應用的結構。除了編輯的成本之外,文件所面對的問題是在變化的過程中維護文件。事實上,在程式碼和文件之間沒有直接的聯絡。沒有自動驗證功能,它能夠檢查文件是否被正確地更新,但是沒有。

為了實現自動驗證功能,使文件儘可能的有效,我認為它應該儘可能地靠近有疑問的程式碼。在程式碼中使用表頭是一種行之有效的辦法。

好的文件必須能夠回答以下的問題:

·  程式碼的目的是什麼?

·  應用了什麼商業規則?

·  它們是怎樣應用的?

·  為什麼選擇特定的技術方案?

·  如果有的話,程式碼應用時有什麼限制?

·  誰於何地,為什麼原因編寫了這段程式碼?

在新增了表頭以後,程式碼如下所示:

/*=================================================================================

描述:  驗證資料

驗證規則:

  * R000051 : 檢查books和video的總數沒有超過最大數目

  * ....

註釋:

  該資料視窗只能由銷售員來進行更新,其它使用者無權修改資料

===================================================================================

修改記錄:

  V1.00  2000-01-01 WINBOY建立

  V1.02  2000-05-11 WINBOY 新增商業法則R000051.

=================================================================================*/

long  ll_currentrow, ll_rowcount

int li_producttype

dec ldc_total

constant int   BOOK = 5, VIDEO = 6

constant dec  MAXAMOUNT = 450000  // 指出books和video的最大數目

CHOOSE CASE dwo.name

  CASE "amount"

 

  //檢查books和video的總數沒有超過最大數目

  //======================================================================

  li_producttype = dw_1.getitemnumber (row, "type")

  IF li_producttype = BOOK OR li_producttype = VIDEO THEN

  // 不考慮當前行資料計算銷售訂單的數目

  //=================================================================

  ll_rowcount = dw_1.rowcount ()

  FOR ll_currentrow = 1 TO  ll_rowcount

  ll_producttype = dw_1.getitemnumber (ll_currentrow , "type")

  IF  li_producttype = BOOK OR li_producttype = VIDEO AND &

  ll_currentrow <> row THEN

  ldc_total += dw_1.getitemnumber (ll_currentrow, "amount")

  END IF

  NEXT

如果您對此有不同的看法,或者有什麼好的意見和建議,可以發E給我: winboy20@sina.com。謝謝各位。

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-992319/,如需轉載,請註明出處,否則將追究法律責任。

相關文章