日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

领域驱动设计案例:Tiny Library:领域模型

發布時間:2025/3/17 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 领域驱动设计案例:Tiny Library:领域模型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本講主要介紹基于Entity Framework的領域驅動設計建模。首先回顧一下Tiny Library的業務邏輯:

  • 任何用戶可以添加Library中的圖書(簡化起見,圖書不能修改也不能刪除),也可以查看圖書的詳細信息
  • 注冊用戶,也就是讀者,可以借書還書、查看自己借過的圖書列表借書信息
  • 請注意上面描述的黑體部分,這些概念出現在Tiny Library的領域知識(Domain Knowledge)中,換言之,是Tiny Library領域的通用語言的組成元素。

    ?

    一、實體與聚合根

    首先分析出實體,不難看出,讀者圖書是實體;由于每個讀者都將有自己的借書信息(比如,什么時候借的哪本書,是否已經歸還,或者是否已經過期),而與之對應地,每本書也可以有被借歷史(比如,這本書是什么時候借給哪個讀者),于是,借書信息也是實體。

    再來看看聚合。借書信息是與讀者和圖書關聯的,也就是說,沒有讀者,借書信息沒有存在的意義,同樣,沒有圖書,借書信息也同樣不存在。每個讀者可以沒有任何借書信息(或者說借書記錄),也可以有多條借書信息;而每本書也同樣可以沒有任何被借信息(或者說被借記錄),也可以有多條被借記錄。因此存在兩個聚合:讀者-借書信息聚合(1..0.*)以及圖書-借書信息聚合(1..0.*)。讀者和圖書分別為聚合根,借書信息為實體。與Tiny Library對應起來,總結如下:

    • 讀者:Reader,聚合根
    • 圖書:Book,聚合根
    • 借書信息:Registration,實體

    根據上述描述,我們可以確定,我們將來需要針對讀者(Reader)和圖書(Book)實現倉儲以及相應的規約。

    ?

    二、基于Entity Framework建立領域模型

    目前Entity Framework支持三種建模方式:Model First、Database First以及Code First。Code First是在今年剛發布的Feature Pack中才支持的。為了迎合領域驅動設計思想,我們采用Model First。

    根據上面的分析,現建模如下:

    注意:如何在Visual Studio中使用Entity Framework進行Model First建模不是本文討論的重點,讀者朋友請自己參閱相關文檔。

    此時,我們需要使用C#部分類的特性,將Reader和Book定義為聚合根,將Registration定義為實體。我開發的一個DDD框架(Apworks)中為聚合根和實體的接口作了定義,現在,只需要引用Apworks的程序集,然后使用部分類的特性,讓Reader和Book實現IAggregateRoot接口,讓Registration實現IEntity接口即可。從技術上看,這樣就將Apworks框架整合到了領域模型中。代碼如下:

    隱藏行號 復制代碼 Reader聚合根
  • public partial class Reader : IAggregateRoot
  • {
  • }
  • ?

    隱藏行號 復制代碼 Book聚合根
  • public partial class Book : IAggregateRoot
  • {
  • }
  • ?

    隱藏行號 復制代碼 Registration實體
  • public partial class Registration : IEntity
  • {
  • }
  • 三、添加業務邏輯

    根據DDD,實體是能夠處理業務邏輯的,應該盡量將業務體現在實體上;如果某些業務牽涉到多個實體,無法將其歸結到某個實體的話,就需要引入領域服務(Domain Service)。Tiny Library案例業務簡單,目前不會涉及到領域服務,因此,在本案例中,業務邏輯都是在實體上處理的。

    以讀者(Reader)為例,它有借書和還書的行為,我們將這兩種行為實現如下:

    隱藏行號 復制代碼 Reader中的業務邏輯
  • public partial class Reader : IAggregateRoot
  • {
  • public void Borrow(Book book)
  • {
  • if (book.Lent)
  • throw new InvalidOperationException("The book has been lent.");
  • Registration reg = new Registration();
  • reg.RegistrationStatus = RegistrationStatus.Normal;
  • reg.Book = book;
  • reg.Date = DateTime.Now;
  • reg.DueDate = reg.Date.AddDays(90);
  • reg.ReturnDate = DateTime.MaxValue;
  • book.Registrations.Add(reg);
  • book.Lent = true;
  • this.Registrations.Add(reg);
  • }
  • public void Return(Book book)
  • {
  • if (!book.Lent)
  • throw new InvalidOperationException("The book has not been lent.");
  • var q = from r in this.Registrations
  • where r.Book.Id.Equals(book.Id) &&
  • r.RegistrationStatus == RegistrationStatus.Normal
  • select r;
  • if (q.Count() > 0)
  • {
  • var reg = q.First();
  • if (reg.Expired)
  • {
  • // TODO: Reader should pay for the expiration.
  • }
  • reg.ReturnDate = DateTime.Now;
  • reg.RegistrationStatus = RegistrationStatus.Returned;
  • book.Lent = false;
  • }
  • else
  • throw new InvalidOperationException(string.Format("Reader {0} didn't borrow this book.",
  • this.Name));
  • }
  • }
  • ?

    業務邏輯的添加仍然是在我們新建的partial class中,這樣做的目的就是為了不讓Entity Framework的代碼自動生成器覆蓋我們手動添加的代碼。相應地,我們在Book和Registration中實現各自的業務邏輯(具體請參見案例源代碼)。從TinyLibrary.Domain這個Project上看,TinyLibrary.edmx定義了基于Entity Framework的領域模型,而其它的幾個C#代碼文件則使用部分類的特性,分別針對每個實體/聚合根實現了一些業務邏輯。

    ?

    下一講將詳細介紹基于TinyLibrary領域模型與Entity Framework的倉儲的實現方式。

    總結

    以上是生活随笔為你收集整理的领域驱动设计案例:Tiny Library:领域模型的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。