軟體複雜度的根本,來源于思維的複雜度。
三層架構從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)
完全代碼下載