|
引言
本文主要是參考Martion Fowler所著的《企業(yè)應(yīng)用架構(gòu)模式》與Eric Evans所著的《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》這兩本泰山之作,加上本人在近年實(shí)際的工作過(guò)程中開(kāi)發(fā)SOA系統(tǒng)所認(rèn)識(shí)到的問(wèn)題所寫(xiě)的一篇文章,歡迎各位點(diǎn)評(píng)。
最后兩節(jié) 細(xì)說(shuō)應(yīng)用層 、系統(tǒng)總體架構(gòu) 是本文的重點(diǎn),著重說(shuō)明領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)與SOA之間的關(guān)系,對(duì)DDD有一定基礎(chǔ)的朋友可以越過(guò)前面的幾節(jié),直接查看第七、八節(jié)。
源代碼下載 (數(shù)據(jù)庫(kù)可以在.edmx文件根據(jù)模型生成)
一、SOA與DDD的定義
SOA與DDD都是常用的系統(tǒng)架構(gòu),但兩者之間所針對(duì)的核心是不同的。
SOA(面向服務(wù)架構(gòu))由Gartner在1996年提出來(lái),它是一種分布式的軟件架構(gòu),它可以根據(jù)需求通過(guò)網(wǎng)絡(luò)對(duì)松散耦合的粗粒度應(yīng)用組件進(jìn)行部署、組合和使用。簡(jiǎn)單來(lái)說(shuō),SOA就是一種大型系統(tǒng)開(kāi)發(fā)的體系架構(gòu),在基于SOA架構(gòu)的系統(tǒng)中,具體應(yīng)用程序的功能是由一些松耦合并且具有統(tǒng)一接口的組件(也就是service)組合構(gòu)建起來(lái)的,它是針對(duì)多核心多平臺(tái)之間的數(shù)據(jù)交換。
DDD(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))由Eric Evans在2004提出,它的核心內(nèi)容是“如何將業(yè)務(wù)領(lǐng)域概念映射到軟件工程當(dāng)中”。它推翻了“軟件從數(shù)據(jù)層開(kāi)發(fā)設(shè)計(jì)”的舊習(xí)慣,強(qiáng)調(diào)領(lǐng)域模型在軟件中發(fā)揮的強(qiáng)大力量,注重如何把企業(yè)內(nèi)部復(fù)雜的業(yè)務(wù)流程轉(zhuǎn)化為軟件。
也許可以認(rèn)為SOA針對(duì)的是大型系統(tǒng)的總體架構(gòu),注重如何把系統(tǒng)進(jìn)行項(xiàng)目分離,隔離開(kāi)發(fā),最后實(shí)現(xiàn)系統(tǒng)合并。而DDD是針對(duì)單個(gè)項(xiàng)目的開(kāi)發(fā)管理過(guò)程,注重如何利用領(lǐng)域模型把業(yè)務(wù)需求轉(zhuǎn)化為軟件。兩者之間并沒(méi)有存在理論上的沖突,能把兩者結(jié)合,各展所長(zhǎng),更能發(fā)揮各自的優(yōu)勢(shì)。
二、DDD的分層結(jié)構(gòu)
1. 概念
從概念上來(lái)說(shuō),領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)架構(gòu)主要分為基礎(chǔ)設(shè)施層、領(lǐng)域?qū)印?a href=/pingce/yingyong/ target=_blank class=infotextkey>應(yīng)用層、表現(xiàn)層4個(gè)概念層。
基礎(chǔ)結(jié)構(gòu)層:是為各層提供各項(xiàng)通用技術(shù)能力而構(gòu)建的,它可以為領(lǐng)域?qū)犹峁┫馠ibernate、LINQ、ADO.NET等持久化機(jī)制,為應(yīng)用層傳遞消息,為表現(xiàn)層提供插件等等。
領(lǐng)域?qū)樱核窍到y(tǒng)的核心部分,代表業(yè)務(wù)的邏輯概念。它會(huì)根據(jù)業(yè)務(wù)的實(shí)際流程定制了業(yè)務(wù)信息以及業(yè)務(wù)規(guī)則,并按一定的關(guān)系制定領(lǐng)域模型。領(lǐng)域模型盡管需要依賴(lài)基礎(chǔ)結(jié)構(gòu)層進(jìn)行保存,但領(lǐng)域模型之間的邏輯關(guān)系是跟基礎(chǔ)結(jié)構(gòu)層相隔離的。即使基礎(chǔ)結(jié)構(gòu)層從NHibernate技術(shù)轉(zhuǎn)換成LINQ技術(shù),也不會(huì)影響到領(lǐng)域?qū)拥慕Y(jié)構(gòu)。領(lǐng)域模型只會(huì)依賴(lài)實(shí)際的業(yè)務(wù)邏輯,它只會(huì)根據(jù)業(yè)務(wù)的轉(zhuǎn)變而靈活變動(dòng)。
應(yīng)用層:它的任務(wù)是協(xié)調(diào)領(lǐng)域?qū)优c表現(xiàn)層之間的關(guān)系,也可以作為系統(tǒng)與外界溝通的橋梁,在這層里面不會(huì)包括任何的業(yè)務(wù)邏輯。在SOA面向服務(wù)架構(gòu),這一層起著重要的作用,在第七節(jié)將詳細(xì)說(shuō)明。
表現(xiàn)層:它是常用的界面開(kāi)發(fā),可以以頁(yè)面(ASP.NET、JSP),窗口(WinForm、WPF、Swing)等形式表現(xiàn),它的主要職責(zé)是負(fù)責(zé)與用戶(hù)進(jìn)行信息溝通。(注意:在一般的項(xiàng)目開(kāi)發(fā)中,Web服務(wù)會(huì)作為與外界通訊的接口放置在表現(xiàn)層中,但在SOA中,Web服務(wù)會(huì)大多置于應(yīng)用層中,下面將會(huì)作進(jìn)一步解釋?zhuān)?/p>
2. 開(kāi)發(fā)實(shí)例
在此先舉個(gè)常見(jiàn)的訂單管理例子,在下面的章節(jié)里都會(huì)以這個(gè)實(shí)例為參考:
每個(gè)用戶(hù)在Person表里面都會(huì)有一個(gè)對(duì)應(yīng)的帳戶(hù),里面記錄了用戶(hù)的姓名、地址、電話(huà)、積分(Point)等基本信息。
在Order表里記錄的是每次交易的過(guò)程,每次商品的送貨費(fèi)(Freightage)為10元,當(dāng)商品價(jià)格(Price)超過(guò)98元可免費(fèi)送貨,當(dāng)用戶(hù)Person積分(Point)超過(guò)2000分可獲7折優(yōu)惠(Favorable),1000~2000分可獲8折,1000分以下可有9折,最后總體價(jià)格為為(TotalPrice)。
在最后結(jié)單的時(shí)候Order表里會(huì)產(chǎn)生訂單號(hào)碼OrderNumber和下訂日期Delivery,Person表的積分也會(huì)加上訂單總價(jià)的點(diǎn)數(shù)。
最后OrderItem表包含了物品Goods、物品價(jià)格Price、購(gòu)買(mǎi)數(shù)量Count等屬性,它主要記錄每次訂單的詳細(xì)交易狀況。
上面的業(yè)務(wù)邏輯跟淘寶、當(dāng)當(dāng)?shù)鹊却笮唾?gòu)物網(wǎng)基本相似。之所以用這樣一個(gè)例子作為參考,是想表現(xiàn)一下DDD是如果利用領(lǐng)域模型去適應(yīng)多變的業(yè)務(wù)邏輯關(guān)系。
三、把業(yè)務(wù)關(guān)系轉(zhuǎn)化為領(lǐng)域模型
1. 概念
模型驅(qū)動(dòng)設(shè)計(jì)(MODEL-DRIVEN-DESIGN)是DDD里面的核心,它代表的是各個(gè)對(duì)象之間的關(guān)系,把復(fù)雜的邏輯關(guān)系轉(zhuǎn)化為模型。
模型主要分為實(shí)體(Entity)、值對(duì)象(Value Object)與服務(wù)(Service)三種。
實(shí)體:實(shí)體所包含的不單止是一連串的屬性,更重要的是與事件的聯(lián)系,在一個(gè)生命周期中環(huán)境的變化與事件發(fā)生,將引起實(shí)體內(nèi)部產(chǎn)生變化。好像在實(shí)體Order里面,Person的積分(Point)和OrderItem的價(jià)格(Price)都會(huì)直接影響總體價(jià)格(TotalPrice)的大小,而總體價(jià)格也會(huì)影響到運(yùn)費(fèi)Freightage的多少等等。在Order實(shí)體的一切,都會(huì)受到Person、OrderItem等這些外部因數(shù)的影響,這樣的對(duì)象被視為實(shí)體。在不同的時(shí)刻,實(shí)體會(huì)有不同的狀態(tài),所以在開(kāi)發(fā)過(guò)程中我們需要為實(shí)體加上一個(gè)“標(biāo)識(shí)符”來(lái)區(qū)分對(duì)象的身份,它是實(shí)體的生命周期里的唯一標(biāo)志。
值對(duì)象:當(dāng)所用到的對(duì)象只有屬性而沒(méi)有其他邏輯關(guān)系的時(shí)候,我們就可以把它視為是值對(duì)象。值對(duì)象沒(méi)有狀態(tài),也不需要有 “標(biāo)識(shí)符”。在多數(shù)情況下它可以作為一個(gè)屬性存在于一個(gè)實(shí)體的內(nèi)部。一般情況下值對(duì)象的屬性是不可改變的,當(dāng)需要更改屬性時(shí),可以把整個(gè)對(duì)象刪除,然后重新加入一個(gè)新對(duì)象。
服務(wù):當(dāng)實(shí)體之間存在某些操作,它們并不單一地附屬于某一個(gè)實(shí)體,而是跟多個(gè)實(shí)體都有關(guān)聯(lián)的時(shí)候,就可以使用服務(wù)來(lái)封裝這些操作。值得注意的是服務(wù)并非單獨(dú)指Web Service, 也并非單單存在于領(lǐng)域?qū)樱窃诟鱾€(gè)層當(dāng)中都會(huì)存在服務(wù),每一層的服務(wù)都有著不同的職能。在基礎(chǔ)結(jié)構(gòu)層服務(wù)可能是用于構(gòu)建身份驗(yàn)證、電子郵件、錯(cuò)誤處理等等操作;在領(lǐng)域?qū)樱?wù)更多時(shí)候是一種操作,它用于協(xié)調(diào)多個(gè)實(shí)體之間的關(guān)系,處理各類(lèi)的業(yè)務(wù)問(wèn)題;在應(yīng)用層(特別是在分布式開(kāi)發(fā)系統(tǒng)內(nèi)),服務(wù)多以Web Service、TCP/IP套接字、MSMQ等等方式實(shí)現(xiàn),服務(wù)在此處會(huì)作為一個(gè)與外界通訊的接口。
- 備注 :這里面也存在一定的爭(zhēng)義,Eric 認(rèn)為實(shí)體所代表的只是多個(gè)對(duì)象之間的關(guān)系,而它們的動(dòng)作將會(huì)由服務(wù)來(lái)體現(xiàn)出來(lái),這被稱(chēng)為貧血型模型。但在開(kāi)發(fā)過(guò)程中,越來(lái)越多人會(huì)把動(dòng)作加入到實(shí)體里面,這被稱(chēng)為充血型模型。其實(shí)不同的問(wèn)題應(yīng)該客觀分析,分別對(duì)待,在這個(gè)例子里面將會(huì)以按照 Eric 的定義來(lái)開(kāi)發(fā)服務(wù),在后面的開(kāi)發(fā)過(guò)程中大家也可以從中體現(xiàn)一下服務(wù)層所帶來(lái)的好處。
2. 實(shí)例說(shuō)明
先以ADO.NET Entity Framework實(shí)現(xiàn)模型,Person、Order分別屬于兩個(gè)實(shí)體,它們都將繼承Root接口,在它們的生命周期內(nèi)都會(huì)生成一個(gè)Guid作為標(biāo)志。此處把OrderItem作為一個(gè)值對(duì)象置于Order實(shí)體內(nèi),這意味著OrderItem會(huì)通過(guò)Order來(lái)獲取,外界不能跨越Order直接獲取OrderItem。當(dāng)然這應(yīng)該由具體的業(yè)務(wù)情況來(lái)確定,當(dāng)外界需要單獨(dú)調(diào)用OrderItem類(lèi)的時(shí)候,就應(yīng)該考慮把OrderItem獨(dú)立成為一個(gè)實(shí)體類(lèi)。
在這里可利用分部類(lèi)為實(shí)體增加Guid屬性,關(guān)于分部類(lèi)于分部方法的詳細(xì)介紹可參考C#綜合揭秘——分部類(lèi)和分部方法
namespace Business.DomainModel
{
public interface Root {
}
public partial class Order:Root
{
private Guid _guid;
public Order()
{
_guid = System.Guid.NewGuid();
}
//為根對(duì)象設(shè)置唯一的Guid;
public Guid GUID
{
get { return _guid; }
}
}
public partial class Person:Root
{
public Person()
{
_guid = System.Guid.NewGuid();
}
//為根對(duì)象設(shè)置唯一的Guid;
private Guid _guid;
public Guid GUID
{
get { return _guid; }
}
}
}
it知識(shí)庫(kù):結(jié)合領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的SOA分布式軟件架構(gòu),轉(zhuǎn)載需保留來(lái)源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。