荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: jek (Super Like Cat), 信区: Program
标  题: 完美程式設計指南--附錄A 程式寫作檢查表
发信站: 荔园晨风BBS站 (Thu Apr  4 07:03:56 2002), 转信

為了提醒你本書的重點,我列出了對程式的幾種檢查要項,你可以在底下這些程式
開發的主要階段中檢查一下:設計,實作,除錯支援,測試,與除錯。我沒列出在
程式開發的整個過程中應該要作的那些項目-我假設你已經打開了編譯器提供的警
告選項,維護了一份除錯版本的程式,有錯誤回報就立刻修正問題等等。

要有效利用這些檢查表,你得在每次在專案中寫上新程式時檢查表上的項目。從實
際的觀點來說,"每次"其實是說"下幾次"你寫新程式之後。這麼做了以後,你應該
就能培養出一種能夠察覺程式有沒違反那些零錯誤程式寫作原則的第六感了。

設計階段
當你考慮一個功能的不同設計方式時,不要光看一個設計方式是不是最快或最小的
。想想實作上、維護上跟使用程式上會出現的風險,對每一種可能的設計方式,檢
查一下這些項目:

設計中有未定義或無意義的行為嗎?會不會出現隨機或罕見的行為?設計中有不必
要的彈性或不必要的假設嗎?設計上有沒有反覆無常的地方?

有資料透過靜態或整體緩衝區傳送嗎?有任何函式依賴其他函式的內部運作機制嗎
?有函式處理超過一件是的嗎?

你的設計必須處理特例嗎?你有將處理特例的程式分離出來嗎?

檢查函式的輸出入資料。每個輸入跟輸出狀態只表示一種資料,或是有包括錯誤狀
態跟其他難以注意到的情形?健全的介面設計會讓每個輸出入資料對程式員都很清
楚明朗而不會遺漏任何如malloc會傳回NULL的錯誤狀態或realloc會在size參數為
0時將記憶體釋放掉之類的重要細節。

預估一下程式員們會如何使用你的函式。那些"明顯"會被用到的使用方式動作正常
嗎?回憶一下realloc造成記憶體塊遺失的例子。

維護上,你的函式在呼叫端可讀嗎?每個函式都應該只處理一件事,參數應該讓呼
叫者了解其意義。TRUE跟FALSE參數的出現經常代表著函式處理超過一件事,或函
式本身設計不良。

你的函式會傳回錯誤值嗎?能不能重新定義那些函式來消除錯誤狀態?記住,函式
傳回錯誤時,在每個呼叫點,錯誤都一定要會被處理到-不然就會出錯。

最重要的,你可以自動徹底的使用單元測試來核對設計的正確性嗎?如果不能,你
應該考慮採用另一種可以測試的設計方式。

實作階段
在實作了設計後,你應該檢查這些項目,確定你的實作健全而防錯:

比較實作與設計之間的差別,你精確的實作了設計的東西嗎?小心,設計與實作之
間的小差異都可能帶來問題。記住先前那個UnsToStr壞掉的例子,就只是因為設計
上要求使用無號整數而實作上寫成了非負整數。

程式中有不必要的假設嗎?在可以使用具可攜性的資料型態時候,你有沒用到不具
移植性的資料型態呢?實作時有沒有什麼草率處理的地方?

檢查程式中的運算式,有溢位或借位的情形嗎?變數也有這些情形嗎?

你有用到巢狀的?:運算子或其他危險的C語言慣用語法,如位元位移替代除法嗎?
你有無緣由的混用位元運算子跟數值運算子嗎?你有用到不可靠的C語言慣用語法
嗎?像在數值運算中使用邏輯運算式產生0/1的值?將危險的寫法用差不多但較安
全的方式重寫吧。

好好檢查一下程式,你有用到團隊中一般程度的程式員看不懂得C語言語法嗎?考
慮用主流的C語言用法重寫一遍吧。

你的每個函式大概都只處理一件事,不過那件工作只用了一條執行路徑去處理,還
是用了不同的執行路線去處理不同的特例呢?如果完成一件事的程式是透過處理特
例的程式碼完成的,你可以使用不同的演算法來消除這些特例嗎?試著消除程式中
的每個if敘述。
?
你有呼叫任何會傳回錯誤的函式嗎?你可以修改設計,讓那樣的用法變得不必要而
可以消除錯誤處理的需要嗎?

你有動到你無權處理的記憶體嗎?特別是那些動到已釋放記憶體的動作?你有讀取
其他子系統擁有的內部資料結構嗎?

如果你的函式使用指向輸入或輸出的指標,你的程式有限制對這些指標的存取只動
到輸出入所需的記憶體嗎?如果沒有,你的程式可能對呼叫者配置出來的記憶體塊
大小作了錯誤的假設。

加上除錯支援階段
加上除錯檢查與其他除錯碼到實作程式中,可以減少找出程式中隱藏的錯誤所需的
時間。底下的檢查表列出了值得讓你考慮使用的除錯檢查根除錯碼:

你有用除錯檢查來核對函式參數嗎?如果你發現自己由於缺乏足夠資訊而沒辦法核
對某一特定參數,提供更多除錯資訊會有用處嗎?回憶一下除錯專用的
sizeofBlock函式對於檢查已配置記憶體塊的指標多有用處。

你用除錯檢查來核對假設條件或找尋未定義行為的違規使用嗎?對未定義行為的檢
查避免程式員們濫用實作上未指定好的地方。

防禦性程式設計方式在內部問題出現時"修正"錯誤,讓這些錯誤找不出來。你有用
除錯檢查在除錯版的程式中找尋這些問題嗎?(當然,這裡對防禦性程式設計方式
的看法不能用在修正使用者的不良輸入所採取的防禦措施上。)

你寫的除錯檢查夠清楚嗎?如果不,確定加上解釋那些檢查用途的注釋。不幸的,
當程式員們碰到一個除錯檢查失敗時而不了解那個檢查的用途時,它們常會假設那
個除錯檢查無用而拿掉它。寫好注釋可以幫你保留下必要的除錯檢查。

如果你的程式配置了記憶體,你有用除錯專用碼來將未初始化的內容設定成某個已
知的明顯垃圾值嗎?將記憶體設定成固定內容將讓找尋跟可靠的重現使用未初始化
記憶體的問題更容易些。

你的程式在釋放記憶體前會先把裡頭的內容填成不合法的垃圾值嗎?

你有演算法重要到讓你該用另一套不同,但是同等功效的除錯用演算法來進行結果
核對嗎?

有什麼除錯檢查可以盡可能在你的程式開頭早期就找出錯誤來嗎?特別是在程式開
頭檢查那些資料表格?

測試階段
程式員們測試自己的程式是件十分重要的事情,即使那會讓程式的推出延期。這一
段落的問題說明了你所應該採取最有用處的測試步驟:

程式編譯時會不會產生任何包括所有選擇性編譯警告的警告訊息?如果你用lint,
 或是類似的診斷工具,你的程式能通過所有的測試嗎?程式能通過你的單元測試
嗎?如果你跳過了其中任何一步,你就正喪失著易於找出錯誤的機會。

你有在除錯程式中,不只注意程式,還留意資料流的去向的,逐步追蹤所有新的程
式碼嗎?這大概是找出你寫的程式中的錯誤的最好辦法了。

你有"翻動"任何程式嗎?如果有,你有測試過更動過的部分嗎?你有在除錯程式中
逐步追蹤過改過的地方嗎?記住,更動過的程式實際上跟必須徹底測試過的新程式
一樣。

你應該替新程式設計單元測試嗎?

除錯階段
在每次找尋一個回報給你的錯誤時,你應該檢查底下的問題:

你找得出那個問題嗎?如果不,記住,一個錯誤不會自己不見;問題一定是隱藏起
來了,或是已經被修好了。要找出是哪一種情形,你應該檢查被回報有問題的那個
程式版本。

你找到了造成錯誤的真正根源,還是只找到了問題帶來的症狀?確實找出問題的根
源來。
?
怎樣自動找出同樣的錯誤?除錯檢查有用嗎?除錯程式碼呢?改變你的程式寫作方
式或寫作過程有用嗎?

--
 === I love Puss forever ===

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.1.241]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店