October 1, 2012

Parameter validation的利器 - Code Contracts

Code Contracts是微軟針對Design by Contract所提出的解決方案。數個月前我在Code Leader一書中也看到類似的東西,作者在書中是以Programming by Contract一詞來代替Design by Contract,提出的解決方案是微軟針對Design by Contract所設計出的程式語言,Spec#。

在寫code時很常需要檢查方法傳入的參數是否有效,如檢查字串是否為空、數值是否大於零或某特定值,如果不符的話就要丟出exception。例如以下程式碼片段
        private static int Add(int x, int y)
        {
            if (x < 0)
            {
                throw new ArgumentException("x cannot be less than 0");
            }

            if (y < 0)
            {
                throw new ArgumentException("y cannot be less than 0");
            }

            return x + y;
        }
寫這些validation不是難事,但要測試這些validation是否可正確執行,在Code Contracts出現之前,我們只能在run time時才能確認validation是否可正常運作。但使用Code Contracts能在compile time時讓我們得知傳入的參數是否有效。這樣一來不僅節省測試所需要的時間,還可以少寫些測試程式。

例如以上程式碼如以Code Contracts來改寫將會如下
        private static int Add(int x, int y)
        {
            Contract.Requires<ArgumentException>(x >= 0, "x cannot be less than 0");
            Contract.Requires<ArgumentException>(y >= 0, "y cannot be less than 0");
            return x + y;
        }
嘗試帶入小於零的x就會得到警告訊息。


當然Code Contracts可以做的不僅於此,這裡先不多做說明。

至於Spec#和Code Contracts要選用哪一個呢?目前來說我會選擇Code Contracts,因為Code Contracts已經可以達到我現階段的需求了。使用Spec#的好處是可以直接利用其所提供的syntax (requires, ensures, etc.)來達到Design by Contract如
public static double Add(int x, int y)
    requires x >= 0;
    requires y >= 0;
{
    return x + y;
}

而且Spec#也可以直接在VS上開發。不過Spec#快一年沒有update,不確定微軟對它的支援度如何,也許之後會整合進C# 5或6也說不定。

參考
  1. Code Contracts
  2. Spec#

No comments: