本文章是由機器翻譯。

程式設計師雜談

Oak 入門:資料驗證與總結

Ted Neward

Ted Neward對於現在的三個列,我一直在探索的橡木為 Web 應用程式空間,帶來的"動態-y"物件方法,它一直騎一個有趣,完成著長期持有的信念有關 Web 應用程式需要如何生成 (或有關的平臺,他們被建) 的幾個挑戰。但每個騎了某個時候,來結束,是時候來總結我的橡樹的探索。我要弄清楚如何確保資料放入系統的使用者是其實不錯的資料,對於初學者。

但第一次......

評注

如果你回去和我走的了,上次看系統,試圖添加一個注釋產量的那些樂於助人的錯誤,另一個通知您"Blog.Controllers.Blog 不包含一個定義為 'AddComment'"這次。相反在靜態類型化的系統中可能會發生什麼 — — 一個編譯錯誤在前門的編譯,部署,運行週期並缺乏的這種方法會絆倒 — — 直到他們實際上企圖不會看到在動態系統中,這些錯誤。一些動態語言支援者聲稱這是動態語言的魅力的一部分,當然不必擔心讓一切一致保持整個系統可以是一件幸事,頭腦是著火的想法和你只需要把這一想法出來到世界時。但我知道誰做了一個大於典型的 Todo 清單中應用程式的專案大多數紅寶石對 Rails 開發人員將首先承認在動態語言中的應用,全面的測試是保持專案的品質高和強大的開發人員的理智的關鍵。所以測試都必須與橡木任何認真的努力的一部分。

不幸的是,當我開始談論測試,我開始進入討論 (單元測試、 效能測試、 集成測試、 聊發展等等),可以輕鬆地消耗自己,另一個打雜志問題的幾個領域和我不想破解這的潘朵拉的盒子。不管您測試方法或偏好,我只想說你必須有某種測試存在橡木應用程式中 (或任何應用程式,但必須是在任何環境中動態類型化高得多),但是你選擇要測試。

同時,AddComment 方法是仍然失蹤。

注釋掉

在這特定的情況下,當使用者鍵入注釋到視圖,它職位給 HomeController 的評論方法,看上去像這樣:

[HttpPost]
public ActionResult Comments(dynamic @params)
{
  dynamic blog = blogs.Single(@params.BlogId);
  blog.AddComment(@params);
  return RedirectToAction("Index");
}

你可以看到,控制器第一次獲得來自表單上,然後用它來在 DynamicRepository 上找到相應的博客條目通過單個方法的 BlogId 參數中藏的博客 ID 然後調用博客。AddComment 來存儲該注釋。 (再次,只是想做點,"贊成"和"反對":此代碼自本系列的第二部分以來一直在地方和我只是現在跑到事實直到現在還沒有存在的 AddComment 方法)。

定義此方法是相當簡單 ; 關於博客類中,添加此方法:

void AddComment(dynamic comment)
{
  // Ignore addition if the body is empty
  if (string.IsNullOrEmpty(comment.Body)) return;
  // Any dynamic property on this instance can be accessed
  // through the "_" property
  var commentToSave = _.NewComment(comment);
  comments.Insert(commentToSave);
}

在此方法中唯一真正的問號是使用底線 (_。NewComment(comment)),是"本"參考的預留位置。 底線已充分認識到的動態性質的此物件,也不會"本"參考 ; 不必擔心差異,底線允許您使用"這個"會,再加上更多的一切。

請注意如何系統的動態性質允許您在代碼中非常節儉。 在命名捆綁在"@params"來控制器中,捕獲表單參數和那些傳遞而不打開其中的任何包裝直接進入添加­發表評論,這反過來將它們傳遞到 NewComment,構造出他們一個動態物件,並將所產生的物件只是獲取插入 DynamicRepository 的評論。 物件的屬性的名稱從何而來? 從起源的這所有的 HTML 表單。

奇怪的是吧嗎? 幾乎感覺你是懶人或東西。

無論如何,都要給它運行,並確保有足夠,現在評論正在添加中。

驗證我

寫到,不過,系統有一個重大缺陷 (好吧,根據使用者的要求,無論如何):它是完全允許的兩個博客條目有確切相同的標題,並不是確定。 (讀者可能會感到迷惑讀哪一個,一個,標題為"LOL Kittehs"或另一個標題為"LOL Kittehs")因此,您需要執行某種獨特性的代碼,所以使用者不能意外地把放在重複標題為博客條目的方式。

在傳統的 Web 框架,這將是一個兩部分工作。 第一,模型物件 (Blog) 將必須定義某種"問我是否我有效"的方法,就沒有什麼真正的原始打 IsValid 和一個定義中的物件,我會打電話給驗證說驗證。 作為一個可能會懷疑從同夥方法工作來説明定義 Blog 和發表評論的物件 (即,它為其橡樹知道來看看一個預定義的名稱) 之間的聯繫的方式,該驗證方法的工作相同的方式 — — 如果一個物件定義了一種驗證方法,然後橡樹將調用物件,反過來將尋找一種驗證方法,問它使此物件有效的所有條件的已定義的 IsValid 方法。

在代碼中,這看起來像這樣:

IEnumerable<dynamic> Validates()
{
  // And define the association
  // For other examples of validations, check out the Oak wiki
  yield return new Uniqueness("Name", blogs);
}

再次,你看到一個流物件描述的驗證要求,交回作為 IEnumerable < 動態 > 的使用 到流中,生成的 C# 的"收益率回歸"設施使用。 從最後一次的架構類,來擴展這是只是跨行"產量返回,"的額外元素就像這樣:

IEnumerable<dynamic> Validates()
{
  // And define the association
  // For other examples of validations check out the Oak wiki
  yield return new Uniqueness("Name", blogs);
  yield return new Length("Name") { Minimum=10, Maximum=199 };
}

橡木 Wiki 定義的完整清單和驗證物件的用法,但一些值得注意的是:

  • 存在:一個欄位不是可選的並且必須是物件的存在。
  • 接受:物件上的欄位必須包含一個特定的值,如 LegalDocument 物件,該物件包含一個 TypedOutAcceptance 欄位在使用者鍵入字串"我接受",表明他接受了法律的限制。
  • 排除:欄位不能包含某些值。
  • 列入:欄位必須是一套的某些值。
  • 格式:通用正則運算式 (使用 Microsoft.NET 框架 Regex 類) 驗證。
  • Numericality:幾乎一切都要與數值包括標記欄位為"整數僅,"做更大-­大於和小於-比的限制或奇偶的簡單測試。
  • 條件:全部捕獲的任何驗證的"逃生艙口"不涵蓋其他地方 — — 一個欄位必須滿足的條件描述使用 lambda 函數。

最後一個條件,不是實際上驗證類型中和的本身,但功能上 (如果不是全部) 的大多數其他驗證類型,目前和因此有點值得更多的解釋。 想像一下一個命令物件,在傳統的電子商務系統中的訂單。 為表示系統、 信用卡卡號只是必要的如果使用者想要使用一張信用卡進行付款。 同樣,要運到的產品只是必要的如果使用者購買數位下載之外的任何位址。 這些兩個意外情況則整齊地使用表示兩個條件驗證,如中所示圖 1

圖 1 條件驗證

public class Order : DynamicModel
{
  public Order()
  {
  }
  public IEnumerable<dynamic> Validates()
  {
    yield return new Presence("CardNumber") {
      If = d => d.PaidWithCard()
    };
    yield return new Presence("Address") {
      Unless = d => d.IsDigitalPurchase()
    };
  }
  public bool PaidWithCard()
  {
    // Could use This().PaymentType instead
    return _.PaymentType == "Card";
  }
  public bool IsDigitalPurchase()
  {
    // Could use This().ItemType instead
    return _.ItemType == "Digital";
  }
}

每個條件物件正在使用的物件的屬性的存在 — — 以及產生一個真/假值 lambda — — 以指示是否存在驗證成功。 在第一個案件中,存在則返回 true (通行證) 如果 d.PaidWithCard,一個本地的方法,如果 PaymentType 欄位等於"一卡通,"則返回 true,則返回 true。 在第二個案件中,存在返回 true 除非 isDigitalPurchase 返回 true,意思如果它是一個數位的專案,沒有位址必要。

所有這些都是準備好與橡木 DynamicModel 派生的任何物件,使用和,如指出事先列中 (msdn.microsoft.com/magazine/dn519929),在介紹這一個,DynamicModel-­派生的物件不必顯式定義的欄位,這些驗證引用。 這些驗證功能不應足夠的任務,順便說一句,這些是所有定義的基架專案橡木資料夾內的 Validations.cs 檔中。 它是定義一個新,如果需要很簡單:只是從 Oak.Validation 繼承並定義至少一種驗證方法,返回真/假。 排斥驗證,例如,是這樣的:

public class Exclusion : Validation
{
  public Exclusion(string property)
    : base(property)
  {
  }
  public dynamic[] In { get; set; }
  public bool Validate(dynamic entity)
  {
    return !In.Contains(PropertyValueIn(entity) as object);
  }
}

在此代碼中的屬性是被排除在外的值存儲 ; 的域 除此之外,這是相當簡單的。 如果需要包含描述性錯誤訊息,驗證提供了一個基本的屬性,錯誤資訊,在其中的描述性消息可以存儲為使用如果驗證失敗。

(對於那些好奇的"協會"從資料庫討論最後一次,這些定義在同一資料夾中的 Association.cs、 Oak.Association,從派生和 — — 正如你可能期望 — — 是有點難度的解釋。 幸運的是,橡樹擁有的大多數傳統關係協會已經定義了,所以不應該會有很多需要在這裡定制。)

橡樹的片斷

有時一個圖書館的部分看起來很酷,但障礙站不能採用整件事,和你只是希望你能挖出它的一小部分和繼續前進。 時,通常最好使用橡木作為一個整體,它不支援的撕扯著它的位想法 (如動態資料庫部分或也許只是動態物件的某些部分,稱為雙子座,我被蓋在 2013 年 8 月問題,在 msdn.microsoft.com/magazine/dn342877) 和使用他們的獨立,沒有系統的其餘部分。 主題上的橡樹 GitHub 頁 (bit.ly/1cjGuou) 針對每個獨立橡木有 NuGet 包部件,為您提供便利轉載 (寫這篇文章):

  • 橡木安裝套裝軟體:這是全橡木套件,它包括 MVC 模型聯程式設計序,生成架構、 橡木 DynamicModel 和支援類、 改版的大規模 (DynamicRepository) 和橡木的核心動態構造雙子星座。
  • 安裝套裝軟體橡木-json:這是關於 JSON 序列化 (可以用在其他 Api) 橡木的一部分。
  • 形成層安裝套裝軟體:這是橡樹,MVC 特定的元件不包括和不包括架構生成的一部分。 形成層包括橡木 DynamicDb,DynamicModel,大量的改編版 (動態­存儲庫) 和橡木核心動態構造雙子星座。
  • 安裝包種子:這是橡木的架構生成。 此 NuGet 包還包括改版的大規模 (用於插入示例資料)。 它不包含任何 MVC 模型聯程式設計序,或橡木 DynamicModel 或支援類。
  • 雙子座安裝套裝軟體:這將安裝只是的核心動態構造動態善良在橡木生成的所有基礎。

之前他們在片中的任何嘗試,我建議想感受如何他們每個人都適合入較大圖片的整個經驗。

利益、 成本和痛苦

可能從這些四列推斷出,有一定好處能夠只是"海闊天空",與更多動態類型化的系統工作。 毫無疑問,成本和疼痛會提高他們醜陋的頭在這樣一個系統 (特別是粗心,和那些對編寫測試未使用),但甚至那些最頑固的靜態類型化偏執者可以學習一些寶貴的意見,從像橡樹的系統。 更重要的是,橡樹可以是原型系統的早期發展極具價值的工具時,物件模型仍然是高度可變和未定義。 最重要的是,橡木 (就是.NET) 的基礎平臺,它變得很可行建議建設在橡樹的 MVC 應用程式中的早期階段,然後慢慢地翻轉它的部分到更靜態類型化 (和,因此,編譯器檢查和編譯器強制執行) 方法如緊緊鎖定的應用程式獲取更多詳細資訊。

個人來說,毫無疑問,橡樹是一個很酷的小專案。 對於我來說,這是很多有趣的功能和想法時出來很小 (相對來說) 包那些時期之一。 橡木肯定進入我個人的工具箱的把戲。

編碼愉快 !

Ted Neward 是的校長 Neward & 同夥 LLC。他已寫一百多篇和創作和合著十幾本書,其中包括"專業 F # 2.0"(Wrox,2010年)。他是 F # 最有價值球員,並在世界各地的會議上講話。他徵求意見,並定期導師 — — 聯繫到他在 ted@tedneward.com 如果你感興趣讓他來與您的團隊一起工作或閱讀他的博客在 blogs.tedneward.com

感謝以下協助校閱本篇文章的技術專家:埃米爾 Rajan (橡木專案建立者)
埃米爾 Rajan 是橡木的建立者。 他是積極發展共同體的成員,在ASP.NETMVC,HTML5,有專長其他體系結構中,紅寶石、 JavaScript/CoffeeScript、 NodeJS,iOS/ObjectiveC 和 F #。 拉詹是真正通曉多種語言與軟體毫不動搖地激情。 他是在 Twitter 上 @amirrajan 和在 Web 上 github.com/amirrajanamirrajan.netimprovingenterprises.com