领域驱动设计案例:Tiny Library:领域模型
本講主要介紹基于Entity Framework的領域驅動設計建模。首先回顧一下Tiny 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聚合根?
Book聚合根?
Registration實體三、添加業務邏輯
根據DDD,實體是能夠處理業務邏輯的,應該盡量將業務體現在實體上;如果某些業務牽涉到多個實體,無法將其歸結到某個實體的話,就需要引入領域服務(Domain Service)。Tiny Library案例業務簡單,目前不會涉及到領域服務,因此,在本案例中,業務邏輯都是在實體上處理的。
以讀者(Reader)為例,它有借書和還書的行為,我們將這兩種行為實現如下:
Reader中的業務邏輯?
業務邏輯的添加仍然是在我們新建的partial class中,這樣做的目的就是為了不讓Entity Framework的代碼自動生成器覆蓋我們手動添加的代碼。相應地,我們在Book和Registration中實現各自的業務邏輯(具體請參見案例源代碼)。從TinyLibrary.Domain這個Project上看,TinyLibrary.edmx定義了基于Entity Framework的領域模型,而其它的幾個C#代碼文件則使用部分類的特性,分別針對每個實體/聚合根實現了一些業務邏輯。
?
下一講將詳細介紹基于TinyLibrary領域模型與Entity Framework的倉儲的實現方式。
總結
以上是生活随笔為你收集整理的领域驱动设计案例:Tiny Library:领域模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JS学习笔记:防止发生命名冲突
- 下一篇: 利用hibernate中的SchemaE