軟件復雜度的根本,來源於思維的復雜度。
三層架構
從DDD看三層
DDD的三層實現詳細架構
看代碼
業務域 (Domain)
持久層 (數據層)
測試和使用的例子
完整代碼下載
得心應手武器庫:
Fluent nHibernate
nUnit
- Git (GitHub)
本文所涉及使用的工具, 見前文: 我的.Net武器庫 ------ 新.Net架構必備工具列表
三層架構
相對於目前日新月異的新概念,新名詞,三層架構已經算得上元老了。雖仍有爭議,但業界更多的是共識。
圖1 常用三層的描述圖
足夠簡單、清晰,我仍要提醒的是,注意層之間連線的箭頭,非常之重要,借用UML的定義,箭頭表示依賴關系。也就是說,必須先有數據層,才有業務層,然后才有表現層。這又怎么樣,小問題。不,這是一個大麻煩!
從DDD看三層
我們暫時靶這個話題放一放,挑個比較新一點的東西。業務域驅動開發(DDD) 近年也是風生水起,紅紅火火,但它是什么,是怎么回事,似乎就不如三層架構那么婦孺皆知了。
圖2 從DDD的角度看三層架構
以業務域為系統的核心,所有其它與業務無關的內容對這個核心來談,都是外部服務/功能。這里,出於本文說明的需要,獨立出了兩個較為特別的外部功能,持久層和用戶接口。
兩個看上去完全不同的架構設計,哪個更對哪個更好?每一個都有大量的擁護者,大量的討論,互相三間似乎又涇渭分明,至少我們經常看到的文章給我們如此的印象。自然,我們的思考,為什么不能融合在一起呢?其實,它們並不像看起來區別那么大。從名詞上,雖然我有意把名稱錯開,我們也仍能看到之間的對應關系、業務層=業務域,數據層=持久層,表現層=用戶接口。當然,這些細節用詞的不同仍有必要的,畢竟,它們不完全是一回事。
DDD的三層實現詳細架構
好了,抽象的討論已經足夠了,我們也足夠糊塗了。細節為王,我們如何實現?來看看這個實際系統的簡化架構圖。.
圖3 實際架構設計
可以看到,在保留了清晰的三層外,重要的是把依賴關系改變了。而所謂依賴注入(DI),只是一種實際的技術實現,完成和實現這種架構設計需求。也可以清晰的看到,圖中是以Domain為核心的。 當然,這是一個簡化又簡化的示意圖,不想一開始就把事情弄的復雜.
看代碼
最后,來看看具體的代碼,才有更好的體驗。
業務域 (Domain)
考試類:
很簡單的一個考試類,可以看到,域中的類定義幾乎不受持久層(數據庫)影響,除了兩點:
1.屬性ID是從數據表的主鍵而來;
2. 如果要用nHibernate的Lazy Load每個屬性都必須是Virtual。
即使如此,這個類已經足夠干凈了。我也看到,一些系統實現,專門定義了一個基礎類Entity,然后,把ID的定義放在這個類中. 我覺得很沒必要, 畫蛇添足。
作為示例,這個域類很簡單, 但卻是核心的核心。項目越往后,這一層膨脹的越厲害。后面幾部分,現在看起來比較多,復雜。之后,不會有大的變化,反而顯得會越來越簡單。
倉儲接口:
注意到:
1. 接口命名,我沒有加I,這是特意的。
2. 用到了Query<>接口, 這個是對查詢的一個抽象。好處是,不需要像大多數的倉儲實現,要為每個類建立一個倉儲接口,膨脹的很厲害。
Quer接口很簡單,沒有任何方法和屬性,只是為了使用強類型。它的實現類會根據需要, 越來越多。 因為,查詢幾乎就是數據層的主要功能。
查詢接口的定義:
持久層 (數據層)
考試映射類:
Fluent nHibernate對倉儲接口的實現:
Fluent nHibernate的配置:
使用的SQLite文本數據庫,作為示例。
測試和使用的例子
自動創建數據庫:
這里,只是用測試的形式,實現功能。如果運行這個測試,將自動生成數據庫。並且,可以輸顯示數據庫生成腳本。在產品環境下,我就是用這個腳本來做數據庫安裝的。
操作數據(模擬UI):
同樣,用測試的形式,模擬UI的數據的操作。
首先,運行Create_a_exam()插入一個考試對象。
然后,運行get_the_exam_by_id()獲取剛插入的考試。
運行 delete_the_exam()刪除考試。
(本文版權屬於© 2012 - 2013 予沁安 | 轉載請注明作者和出處WangHaoBlog.com)