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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

结合领域驱动设计的SOA分布式软件架构

發(fā)布時(shí)間:2024/1/17 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 结合领域驱动设计的SOA分布式软件架构 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

引言

本文主要是參考Martion Fowler所著的《企業(yè)應(yīng)用架構(gòu)模式》與Eric Evans所著的《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》這兩本泰山之作,加上本人在近年實(shí)際的工作過程中開發(fā)SOA系統(tǒng)所認(rèn)識(shí)到的問題所寫的一篇文章,歡迎各位點(diǎn)評(píng)。
最后兩節(jié)? 細(xì)說應(yīng)用層系統(tǒng)總體架構(gòu)?是本文的重點(diǎn),著重說明領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)與SOA之間的關(guān)系,對(duì)DDD有一定基礎(chǔ)的朋友可以越過前面的幾節(jié),直接查看第七、八節(jié)。

源代碼下載 (數(shù)據(jù)庫可以在.edmx文件根據(jù)模型生成)

?

目錄

一、SOA與DDD的定義

二、DDD的分層結(jié)構(gòu)

三、把業(yè)務(wù)關(guān)系轉(zhuǎn)化為領(lǐng)域模型

四、細(xì)說Repository

五、領(lǐng)域?qū)拥姆?wù)

六、工廠模式Factory

七、細(xì)說應(yīng)用層

八、系統(tǒng)總體架構(gòu)?

?

?

一、SOA與DDD的定義

SOA與DDD都是常用的系統(tǒng)架構(gòu),但兩者之間所針對(duì)的核心是不同的。

SOA(面向服務(wù)架構(gòu))由Gartner 在1996年提出來,它是一種分布式的軟件架構(gòu),它可以根據(jù)需求通過網(wǎng)絡(luò)對(duì)松散耦合的粗粒度應(yīng)用組件進(jìn)行部署、組合和使用。簡單來說,SOA就是一種大型系統(tǒng)開發(fā)的體系架構(gòu),在基于SOA架構(gòu)的系統(tǒng)中,具體應(yīng)用程序的功能是由一些松耦合并且具有統(tǒng)一接口的組件(也就是service)組合構(gòu)建起來的,它是針對(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ù)層開發(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)目分離,隔離開發(fā),最后實(shí)現(xiàn)系統(tǒng)合并。而DDD是針對(duì)單個(gè)項(xiàng)目的開發(fā)管理過程,注重如何利用領(lǐng)域模型把業(yè)務(wù)需求轉(zhuǎn)化為軟件。兩者之間并沒有存在理論上的沖突,能把兩者結(jié)合,各展所長,更能發(fā)揮各自的優(yōu)勢(shì)。

回到目錄

二、DDD的分層結(jié)構(gòu)

1. 概念

從概念上來說,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)架構(gòu)主要分為基礎(chǔ)設(shè)施層、領(lǐng)域?qū)印?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ū)?#xff1a;它是系統(tǒng)的核心部分,代表業(yè)務(wù)的邏輯概念。它會(huì)根據(jù)業(yè)務(wù)的實(shí)際流程定制了業(yè)務(wù)信息以及業(yè)務(wù)規(guī)則,并按一定的關(guān)系制定領(lǐng)域模型。領(lǐng)域模型盡管需要依賴基礎(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ì)依賴實(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ì)說明

表現(xiàn)層:它是常用的界面開發(fā),可以以頁面(ASP.NET、JSP),窗口(WinForm、WPF、Swing)等形式表現(xiàn),它的主要職責(zé)是負(fù)責(zé)與用戶進(jìn)行信息溝通。(注意:在一般的項(xiàng)目開發(fā)中,Web服務(wù)會(huì)作為與外界通訊的接口放置在表現(xiàn)層中,但在SOA中,Web服務(wù)會(huì)大多置于應(yīng)用層中,下面將會(huì)作進(jìn)一步解釋)

?

2. 開發(fā)實(shí)例

在此先舉個(gè)常見的訂單管理例子,在下面的章節(jié)里都會(huì)以這個(gè)實(shí)例為參考

每個(gè)用戶在Person表里面都會(huì)有一個(gè)對(duì)應(yīng)的帳戶,里面記錄了用戶的姓名、地址、電話、積分(Point)等基本信息。

在Order表里記錄的是每次交易的過程,每次商品的送貨費(fèi)(Freightage)為10元,當(dāng)商品價(jià)格(Price)超過98元可免費(fèi)送貨,當(dāng)用戶Person積分(Point)超過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、購買數(shù)量Count等屬性,它主要記錄每次訂單的詳細(xì)交易狀況。

上面的業(yè)務(wù)邏輯跟淘寶、當(dāng)當(dāng)?shù)鹊却笮唾徫锞W(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ì)設(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),所以在開發(fā)過程中我們需要為實(shí)體加上一個(gè)“標(biāo)識(shí)符”來區(qū)分對(duì)象的身份,它是實(shí)體的生命周期里的唯一標(biāo)志。

值對(duì)象:當(dāng)所用到的對(duì)象只有屬性而沒有其他邏輯關(guān)系的時(shí)候,我們就可以把它視為是值對(duì)象。值對(duì)象沒有狀態(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ù)來封裝這些操作。值得注意的是服務(wù)并非單獨(dú)指Web Service, 也并非單單存在于領(lǐng)域?qū)?/strong>,而是在各個(gè)層當(dāng)中都會(huì)存在服務(wù),每一層的服務(wù)都有著不同的職能。在基礎(chǔ)結(jié)構(gòu)層服務(wù)可能是用于構(gòu)建身份驗(yàn)證、電子郵件、錯(cuò)誤處理等等操作;在領(lǐng)域?qū)?#xff0c;服務(wù)更多時(shí)候是一種操作,它用于協(xié)調(diào)多個(gè)實(shí)體之間的關(guān)系,處理各類的業(yè)務(wù)問題;在應(yīng)用層(特別是在分布式開發(fā)系統(tǒng)內(nèi)),服務(wù)多以Web Service、TCP/IP套接字、MSMQ等等方式實(shí)現(xiàn),服務(wù)在此處會(huì)作為一個(gè)與外界通訊的接口;

  • 備注 :這里面也存在一定的爭義,Eric 認(rèn)為實(shí)體所代表的只是多個(gè)對(duì)象之間的關(guān)系,而它們的動(dòng)作將會(huì)由服務(wù)來體現(xiàn)出來,這被稱為貧血型模型。但在開發(fā)過程中,越來越多人會(huì)把動(dòng)作加入到實(shí)體里面,這被稱為充血型模型。其實(shí)不同的問題應(yīng)該客觀分析,分別對(duì)待,在這個(gè)例子里面將會(huì)以按照 Eric 的定義來開發(fā)服務(wù),在后面的開發(fā)過程中大家也可以從中體現(xiàn)一下服務(wù)層所帶來的好處。

?

2. 實(shí)例說明

先以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ì)通過Order來獲取,外界不能跨越Order直接獲取OrderItem。當(dāng)然這應(yīng)該由具體的業(yè)務(wù)情況來確定,當(dāng)外界需要單獨(dú)調(diào)用OrderItem類的時(shí)候,就應(yīng)該考慮把OrderItem獨(dú)立成為一個(gè)實(shí)體類。

在這里可利用分部類為實(shí)體增加Guid屬性,關(guān)于分部類于分部方法的詳細(xì)介紹可參考C#綜合揭秘——分部類和分部方法

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; }
}
}
}

回到目錄?

?四、細(xì)說Repository

1.概念

Repository是把持久化對(duì)象轉(zhuǎn)換成領(lǐng)域模型的一種方式,可用于獲取、更新持久對(duì)象并管理它們的生命周期。它使應(yīng)用程序與持久化技術(shù)實(shí)現(xiàn)解耦,程序無需受制于使用Oracle還是MySql數(shù)據(jù)庫,也不會(huì)受到Hibernate、LINQ、ADO.NET等數(shù)據(jù)層的約束,使開發(fā)人員可以把注意力集中到領(lǐng)域模型當(dāng)中。

Repository與傳統(tǒng)三層模式的DAL層有點(diǎn)相似,但Repository針對(duì)的是每一個(gè)根對(duì)象來劃分邊界的。在這個(gè)例子當(dāng)中,Person與Order都會(huì)有對(duì)應(yīng)的PersonRepository、OrderRepository。而OrderItem只是Order的子屬性,所以它的插入、更新、刪除都會(huì)包含在OrderRepository當(dāng)中。當(dāng)多個(gè)對(duì)象之間建立起聯(lián)系后,關(guān)系將是復(fù)雜的,特別是在LINQ里面,程序可以輕易通過Person的導(dǎo)航屬性里獲取OrderItem的值,最后很容易使代碼變得混亂。所以確立Repository的邊界,可以在有效管理每個(gè)Repository的職能。

2.實(shí)例說明

注意OrderItem的存取、刪除都包含在OrderRepository里面。在獲取、修改Order的時(shí)候,也會(huì)利用“顯式加載” context.Order.Include("OrderItem") 的方法,使OrderItem實(shí)現(xiàn)同步更新。而通過PersonRepository.GetPerson(int )獲取的Person對(duì)象,它內(nèi)部的Order屬性將是null值,這必須清晰按照領(lǐng)域模型的邊界劃分的。

當(dāng)LINQ面世以后,數(shù)據(jù)的獲取變得簡單,特別在一些小型的系統(tǒng)開發(fā)時(shí),很多人會(huì)不自覺地把這種領(lǐng)域模型的分界規(guī)則打破。但隨著系統(tǒng)的復(fù)雜化,問題就會(huì)逐漸呈現(xiàn)。比如當(dāng)Order對(duì)象的屬性被更新,使用OrderRepository.Update(Order)更新數(shù)據(jù)庫后,頁面的Person對(duì)象未能同步實(shí)現(xiàn)更新,在Person與數(shù)據(jù)庫交換數(shù)據(jù)的時(shí)候,Order又被變回舊值。

在混亂的數(shù)據(jù)層開發(fā)中,這種情況非常常見,所以在下會(huì)堅(jiān)持Repository的原則,把Repository的職能清晰按照領(lǐng)域模型劃分。

namespace Business.IRepository
{
public interface IOrderRepository
{
Order GetOrder(int id);
IList<Order> GetList();
IList<Order> GetListByPerson(int personID);
int AddOrder(Order order);
int DeleteOrder(int id);
int UpdateOrder(Order order);

int AddOrderItem(OrderItem orderItem);
int DeleteOrderItem(int id);
}

public interface IPersonRepository
{
int AddPerson(Person person);
int AttachPerson(Person person);
int UpdatePerson(Person person);
Person GetPerson(int id);
IList<Person> GetList();
}
}

namespace Business.Repository
{
public class OrderRepository:IOrderRepository
{
//根據(jù)ID獲取單個(gè)Order
public Order GetOrder(int id)
{
BusinessContext _context = new BusinessContext();
Order order = null;

try
{
using (TransactionScope scope = new TransactionScope())
{
//由于OrderItem是Order實(shí)體中的一個(gè)屬性,必須通過OrderRepository同步獲取
var list = _context.Order.Include("OrderItem")
.Where(x => x.ID == id);
if (list.Count() > 0)
order = list.First();
else
order = new Order();
scope.Complete();
}
}
catch (Exception ex)
{
//出錯(cuò)處理,并返回一個(gè)空對(duì)象
Business.Common.ExceptionManager.DataException.DealWith(ex);
order = new Order();
}
_context.Dispose();
return order;
}
..................
..................
}

public class PersonRepository:IPersonRepository
{
public int AddPerson(Person person)
{
return LinqHelp.Add<Person>(person);
}

public Person GetPerson(int id)
{
return LinqHelp.Get<Person>(id);
}
.................
.................
}
}

在更新Order這種復(fù)雜的領(lǐng)域模型時(shí),如果要分辨單個(gè)OrderItem屬性是新建值還是更新值,然后分別處理,那將是比較麻煩的,而且OrderItem只是一個(gè)值對(duì)象,ID編碼等屬性對(duì)它沒有任何實(shí)在意義。所以在更新List<OrderItem>屬性時(shí)都會(huì)先把它全部刪除,然后重新加載,在OrderItem數(shù)量不多的時(shí)候,這是一種十分有效的方法。

namespace Business.Repository
{
public class OrderRepository:IOrderRepository
{
.................
.................
//更新Order,因?yàn)殡y以別哪些是原有的OrderItem,哪些OrderItem是新插入
//使用簡單的方法,會(huì)先把原有的OrderItem的刪除,再重新插入
public int UpdateOrder(Order order)
{
int returnValue = -1;
BusinessContext _context = new BusinessContext();

try
{
using (TransactionScope scope = new TransactionScope())
{
var list = _context.Order.Include("OrderItem")
.Where(x => x.ID == order.ID);
if (list.Count() > 0)
{
//更新Order列
Order _order = list.First();
_order.Count = order.Count;
_order.Delivery = order.Delivery;
_order.Favorable = order.Favorable;
_order.Freightage = order.Freightage;
_order.OrderNumber = order.OrderNumber;
_order.PersonID = order.PersonID;
_order.Price = order.Price;
_order.TotalPrice = order.TotalPrice;

//刪除原有的訂單明細(xì)項(xiàng)OrderItem
if (list.First().OrderItem.Count != 0)
foreach (var item in list.First().OrderItem)
DeleteOrderItem(item.ID);
//加入新的訂單明細(xì)項(xiàng)OrderItem
if (order.OrderItem.Count != 0)
{
foreach (var item in order.OrderItem)
{
var _orderItem = new OrderItem();
_orderItem.Count = item.Count;
_orderItem.Goods = item.Goods;
_orderItem.OrderID = item.OrderID;
_orderItem.Price = item.Price;
AddOrderItem(_orderItem);
}
}
returnValue = _context.SaveChanges();
}
else
returnValue = 0;

scope.Complete();
}
}
catch (Exception ex)
{
Business.Common.ExceptionManager.DataException.DealWith(ex);
returnValue=-1;
}

_context.Dispose();
return returnValue;
}

//插入OrderItem
public int AddOrderItem(OrderItem orderItem)
{
return LinqHelp.Add<OrderItem>(orderItem);
}

//刪除OrderItem
public int DeleteOrderItem(int id)
{
EntityKey key = new EntityKey("BusinessContext.OrderItem", "ID", id);
return LinqHelp.Delete(key);
}
}
}

回到目錄?

五、領(lǐng)域?qū)拥姆?wù)

1. 例子說明

在第二節(jié)已基本介紹過服務(wù)的作用了,領(lǐng)域?qū)臃?wù)的作用主要是為了解決業(yè)務(wù)上的邏輯問題,更多的時(shí)候,服務(wù)是一個(gè)與業(yè)務(wù)相關(guān)的動(dòng)作。比如在上述例子中:

在Order表里記錄的是每次交易的過程,每次商品的送貨費(fèi)(Freightage)為10元,當(dāng)商品價(jià)格(Price)超過98元可免費(fèi)送貨,當(dāng)用戶 Person積分(Point)超過2000分可獲7折優(yōu)惠(Favorable),1000~2000分可獲8折,1000分以下可有9折,最后總體價(jià) 格為為(TotalPrice)。

這復(fù)雜的業(yè)務(wù)邏輯,完全可以由一個(gè)領(lǐng)域服務(wù)類AccountManager來完成

namespace Business.Service.DomainService
{
public class AccountManager
{
private Person _person;
private Order _order;

public AccountManager(Person person, Order order)
{
_person = person;
_order = order;
}

///計(jì)算總體收費(fèi)
public void Account()
{
//計(jì)算商品數(shù)量
GoodsCount();
//計(jì)算商品價(jià)格
PriceAccount();
//計(jì)算優(yōu)惠等級(jí)
FavorableAccount();
double price1 = (_order.Price - _order.Favorable).Value;
//計(jì)算運(yùn)費(fèi)
FreightageAccount(price1);
//計(jì)算總體價(jià)費(fèi)
_order.TotalPrice = price1 + _order.Freightage.Value;
}

//計(jì)算商品數(shù)量
private void GoodsCount()
{
_order.Count=0;
foreach (var OrderItem in _order.OrderItem)
_order.Count += OrderItem.Count;
}

//商品總體價(jià)格
private void PriceAccount()
{
_order.Price = 0;
foreach (var OrderItem in _order.OrderItem)
_order.Price += OrderItem.Price * OrderItem.Count;
}

//優(yōu)惠分為三等,積分小于1000有9折,小于2000分為8折,大于2000為7折
private void FavorableAccount()
{
int point = (int)_person.Point.GetInt();

if (point < 1000)
_order.Favorable = _order.Price * 0.1;
if (point >= 1000 && point < 2000)
_order.Favorable = _order.Price * 0.2;
if (point > 2000)
_order.Favorable = _order.Price * 0.3;
}

//如果價(jià)格在98元以上,可免運(yùn)費(fèi)。其余運(yùn)費(fèi)為10元
private void FreightageAccount(double price)
{
if (price >= 98)
_order.Freightage = 0;
else
_order.Freightage = 10;
}
}
}

你可能會(huì)說,在這個(gè)業(yè)務(wù)流程中,除了積分優(yōu)惠Person.Point以外,其他的業(yè)務(wù)都只與Order的屬性有關(guān),按照充血型模型的方案,完全可以把這些業(yè)務(wù)放到Order的方法當(dāng)中,而把積分優(yōu)惠獨(dú)立成為一個(gè)服務(wù)。但在下在很多的開發(fā)過程中發(fā)現(xiàn),為模型附上動(dòng)作會(huì)帶來一連串的問題,好像你不知道哪些操作應(yīng)該在模型動(dòng)作上實(shí)現(xiàn),哪里應(yīng)該在服務(wù)中實(shí)現(xiàn)......。對(duì)于這些無休止的爭論不會(huì)因?yàn)檫@里的一個(gè)小例子而停止,但在這里我會(huì)堅(jiān)持使用貧血型模型,利用服務(wù)來完成所有的動(dòng)作。

再舉一個(gè)例子:在最后結(jié)單的時(shí)候Order表里會(huì)產(chǎn)生訂單號(hào)碼OrderNumber和下訂日期Delivery,Person表的積分也會(huì)加上訂單總價(jià)的點(diǎn)數(shù)。對(duì)應(yīng)這個(gè)操作,也可以單獨(dú)開發(fā)一個(gè)PaymentManager服務(wù)類進(jìn)行管理。

namespace Business.Service.DomainService
{
public class PaymentManager
{
//下單結(jié)算
public void Payment(Order order,Person person)
{
//確定下單,建立訂單號(hào)
order.OrderNumber = Guid.NewGuid().ToString();
order.Delivery = DateTime.Now;
//增加積分
if (person.Point.HasValue)
person.Point += (int)order.TotalPrice.GetValueOrDefault();
else
person.Point = (int)order.TotalPrice.GetValueOrDefault();
}
}
}

利用領(lǐng)域?qū)拥姆?wù),使得每個(gè)Manager服務(wù)類的職能非常明確,業(yè)務(wù)管理起來也十分地方便,領(lǐng)域?qū)涌梢噪S著業(yè)務(wù)的改變而靈活變動(dòng)。而且領(lǐng)域?qū)泳哂?“高內(nèi)聚,低耦合” 特性,它并不依賴其它任何一層,而只是把業(yè)務(wù)邏輯包含在里面。

回到目錄?

六、工廠模式Factory

Factory是常用到軟件開發(fā)模式,在網(wǎng)上像簡單工廠、工廠方法、抽象工廠等開發(fā)模式的資料都到處可尋,可這并不是領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的主題。在這一節(jié)里,我主要想介紹Factory的適用時(shí)機(jī)。

并非生成所有對(duì)象的時(shí)候,都需要用到工廠模式。在生成簡單對(duì)象的時(shí)候,可以直接利用構(gòu)造函數(shù)來代替工廠,也可以添加工廠方法來生成對(duì)象。但如果在生成對(duì)象時(shí),內(nèi)部屬性之間存在一系統(tǒng)復(fù)雜的業(yè)務(wù)規(guī)則的時(shí)候,就可以把生成方法獨(dú)立到一個(gè)Factory類里面。這時(shí)候客戶端無需理會(huì)潛在邏輯關(guān)系,而直接通過這個(gè)Factory來生成相應(yīng)的對(duì)象。

舉個(gè)例子,在新建Order的時(shí)候,業(yè)務(wù)上規(guī)定運(yùn)費(fèi)是總體金額的1%,折扣規(guī)定是7.5折...... 。如果由客戶端新建一個(gè)對(duì)象Order,然后為這些屬性負(fù)值,那相關(guān)的業(yè)務(wù)邏輯就會(huì)暴露在外。這時(shí)候就可以使用Factory模式,把屬性之間的關(guān)系封裝到Factory之內(nèi),客戶端通過Factory就能輕松地生成Order對(duì)象而無需要理會(huì)復(fù)雜的內(nèi)部關(guān)系。

至于較復(fù)雜的Factory模式,在此不多作介紹,各位可以在網(wǎng)上查找相關(guān)資料。

回到目錄?

七、細(xì)說應(yīng)用層

1. SOA系統(tǒng)中應(yīng)用層的特點(diǎn)

在開發(fā)SOA分布式系統(tǒng)的時(shí)候,應(yīng)用層是一個(gè)重點(diǎn),它主要有兩個(gè)作用。

第一,應(yīng)用層主要作用是協(xié)調(diào)領(lǐng)域?qū)庸ぷ?#xff0c;指揮領(lǐng)域?qū)ο蠼鉀Q業(yè)務(wù)問題,但應(yīng)用層本身不會(huì)牽扯到業(yè)務(wù)狀態(tài)。

第二,在SOA系統(tǒng)當(dāng)中應(yīng)用層是數(shù)據(jù)運(yùn)輸中心和信息發(fā)放的端口,擔(dān)負(fù)著數(shù)據(jù)轉(zhuǎn)換與數(shù)據(jù)收發(fā)的責(zé)任。

它有以下的特點(diǎn):

  • 粗粒度

分布式系統(tǒng)與普通網(wǎng)站和應(yīng)用程序不同,因?yàn)樗俣ㄍ饨鐚?duì)系統(tǒng)內(nèi)部是毫無了解的,用戶只想輸入相關(guān)數(shù)據(jù),最后得到一系列計(jì)算結(jié)果。所以我們應(yīng)該把計(jì)算結(jié)果封裝在一個(gè)數(shù)據(jù)傳輸對(duì)象(DTO)內(nèi),實(shí)現(xiàn)粗粒度的傳遞,這是一般項(xiàng)目與SOA系統(tǒng)在服務(wù)層的一個(gè)最明顯的差別。 想想如果一個(gè)頁面需要同時(shí)顯示一個(gè)顧客的個(gè)人資料、某張訂單的詳細(xì)資料,那將要同時(shí)獲取Person、Order、OrderItem三張表的信息。在普通系統(tǒng)的開發(fā)過程中,這并不會(huì)造成太大問題,但在使用遠(yuǎn)程服務(wù)的時(shí)候,如果用三個(gè)方法分別獲取,那將會(huì)造成不少的性能損耗。特別是在分布式開發(fā)系統(tǒng)中,應(yīng)用層與表現(xiàn)層之間是實(shí)現(xiàn)分離的,更多時(shí)候兩者是由不同部門所開發(fā)的模塊,表現(xiàn)層不會(huì)了解應(yīng)用層中的邏輯關(guān)系,Person,Order,OrderItem三樣?xùn)|西在表現(xiàn)層看來,也就是同一樣?xùn)|西,那就是返回值。所以在系統(tǒng)內(nèi),應(yīng)該把多張表的信息封裝在一個(gè)DTO對(duì)象內(nèi),通過應(yīng)用層一個(gè)遠(yuǎn)程方法一次性返還。使用粗粒度的數(shù)據(jù)元素是分布式系統(tǒng)的一個(gè)特點(diǎn)

  • 傳輸性

如果你熟悉SOA系統(tǒng),對(duì)DTO(Data Transfer Object 數(shù)據(jù)傳輸對(duì)象)這個(gè)詞一定并不陌生。DTO屬于一個(gè)數(shù)據(jù)傳輸?shù)妮d體,內(nèi)部并不存在任何業(yè)務(wù)邏輯,通過DTO可以把內(nèi)部的領(lǐng)域?qū)ο笈c外界隔離。DTO所封裝的是客戶端的數(shù)據(jù),所以它的設(shè)計(jì)更多地是針對(duì)客戶端的需求,而不是業(yè)務(wù)邏輯。比如說本來Person與Order是一對(duì)多的關(guān)系,但當(dāng)一個(gè)頁面只要顯示的是一個(gè)客戶的單張訂單信息,那我們就可以根據(jù)需要把DTO中的Person和Order設(shè)計(jì)為一對(duì)一的關(guān)系。如果你是使用MVC開發(fā)一般的網(wǎng)站,更多時(shí)候會(huì)把返回對(duì)象直接轉(zhuǎn)化為Model。如果你開發(fā)是一個(gè)分布式系統(tǒng),那更多時(shí)候會(huì)從系統(tǒng)性能與隱藏業(yè)務(wù)邏輯出發(fā)著想。而且考慮到把內(nèi)部對(duì)象轉(zhuǎn)化為DTO,將是一件麻煩的事,建議應(yīng)該考慮DTO的兼容性,使DTO可以作為多個(gè)方法的返還載體。(注意:在SOA系統(tǒng)內(nèi),應(yīng)該從性能出發(fā)優(yōu)先考慮粗粒度元素的傳輸性問題)

  • 封裝性

在SOA系統(tǒng)當(dāng)中應(yīng)用層服務(wù)的發(fā)布并不需要復(fù)雜的模型,只需使用外觀模式(Facade)把一些功能封裝在少數(shù)的幾個(gè)服務(wù)類里面,使用Web Service、TCP/IP套接字、MSMQ等服務(wù)方式向外界發(fā)布。

說到這里,我真的十分感激Martin先生帶給我的幫助,在開發(fā)過程中,這些復(fù)雜的問題帶給我不少的困擾,Martin先生一紙富有經(jīng)驗(yàn)的獨(dú)特見解,真的帶給在下很大的啟發(fā)。

2. 應(yīng)用層的協(xié)調(diào)性

應(yīng)用層服務(wù)會(huì)利用Repository,完成實(shí)體基本的插入、更新、獲取等等操作,并調(diào)用領(lǐng)域?qū)拥姆?wù)管理的業(yè)務(wù)邏輯。注意觀察,一切的業(yè)務(wù)邏輯都只會(huì)隱藏于領(lǐng)域?qū)?#xff0c;應(yīng)用層服務(wù)只起著協(xié)調(diào)作用,本身不應(yīng)該包含有任何業(yè)務(wù)邏輯。

可以看到OrderService就是通過調(diào)用AccountManager、PaymentManager等領(lǐng)域?qū)臃?wù)來完成結(jié)賬、付款等一系列復(fù)雜業(yè)務(wù)邏輯的。

namespace Business.Service.ApplicationService
{
public class PersonService
{
private IPersonRepository personRepository = DataAccess.CreatePersonRepository();

public int AddPerson(Person person)
{
return personRepository.AddPerson(person);
}

public int UpdatePerson(Person person)
{
return personRepository.UpdatePerson(person);
}

public Person GetPerson(int personID)
{
return personRepository.GetPerson(personID);
}

public IList<Person> GetList()
{
return personRepository.GetList();
}
}

public class OrderService
{
private IOrderRepository orderRepository = DataAccess.CreateOrderRepository();

public int AddOrder(Order order)
{
//計(jì)算Order總體費(fèi)用
Account(order);
//加入修改后的Order
return orderRepository.AddOrder(order);
}

//調(diào)用領(lǐng)域?qū)臃?wù)AccountManager,計(jì)算Order總體費(fèi)用
private void Account(Order order)
{
//獲取對(duì)應(yīng)Person對(duì)象
IPersonRepository personRepository = DataAccess.CreatePersonRepository();
Person person = personRepository.GetPerson(order.PersonID);

//調(diào)用服務(wù)層的AccountManager對(duì)象,計(jì)算費(fèi)用,修改Order
AccountManager accountManager = new AccountManager(person, order);
accountManager.Account();
}

//調(diào)用領(lǐng)域?qū)臃?wù)PaymentManager,確認(rèn)訂單
public Order Payment(int orderID)
{
var order=orderRepository.GetOrder(orderID);
if (order != null)
{
PersonRepository personRepository = new PersonRepository();
var person=personRepository.GetPerson(order.PersonID);

PaymentManager paymentManager = new PaymentManager();
paymentManager.Payment(order, person);

orderRepository.UpdateOrder(order);
personRepository.UpdatePerson(person);

return order;
}
else
throw new Exception("Can not find order!");
}

public int DeleteOrder(Order order)
{
return orderRepository.DeleteOrder(order.ID);
}

public Order GetOrder(int orderID)
{
return orderRepository.GetOrder(orderID);
}

public IList<Order> GetList()
{
return orderRepository.GetList();
}

public IList<Order> GetListByPerson(int personID)
{
return orderRepository.GetListByPerson(personID);
}

public int UpdateOrder(Order order)
{
Account(order);
return orderRepository.UpdateOrder(order);
}

public int AddOrderItem(OrderItem orderItem)
{
int index = orderRepository.AddOrderItem(orderItem);
Order order = orderRepository.GetOrder(orderItem.OrderID);
UpdateOrder(order);
return index;
}

public int DeleteOrderItem(OrderItem orderItem)
{
int index = orderRepository.DeleteOrderItem(orderItem.ID);
Order order = orderRepository.GetOrder(orderItem.OrderID);
UpdateOrder(order);
return index;
}
.......................
.......................
}
}

?

3. 數(shù)據(jù)轉(zhuǎn)換過程

前面已經(jīng)解釋了DTO的作用,但實(shí)現(xiàn)領(lǐng)域?qū)ο笈cDTO之間的轉(zhuǎn)換是一件復(fù)雜的事件,因此可以建立一個(gè)數(shù)據(jù)轉(zhuǎn)換器實(shí)現(xiàn)此功能。

在平常的工作里,不太多會(huì)把“訂單管理系統(tǒng)”做成SOA的模式,因?yàn)樵诜植际较到y(tǒng)中,數(shù)據(jù)的格式與定義大多數(shù)由部門之間協(xié)定,其中包含明確的規(guī)則。但由于條件的局限,在這里還是想以訂單管理為例子,希望可以帶給你一定的幫助。例子如下:在購物車結(jié)賬,頁面會(huì)包含用戶基本信息,當(dāng)前訂單信息,訂單明細(xì)信息等多個(gè)部分。

?

?

要完成數(shù)據(jù)轉(zhuǎn)換,首先可以根據(jù)頁面建立DTO對(duì)象,在分布式系統(tǒng)中,通常會(huì)把DTO對(duì)象放在一個(gè)獨(dú)立的命名空間里,在這個(gè)實(shí)例里面稱之為Business.TransferObject。DTO對(duì)象更多時(shí)候是面向表現(xiàn)層的需求而建立,這里由于表現(xiàn)層頁面所需要的只是單個(gè)用戶,單張訂單的數(shù)據(jù),所以在OrderDTO對(duì)象里會(huì)包含了用戶信息和訂單資料,也存在訂單詳細(xì)列List<OrderItemDTO>。當(dāng)然,DTO的設(shè)計(jì)可以隨著需求而修改。

在SOA系統(tǒng)里,DTO是遠(yuǎn)程服務(wù)數(shù)據(jù)的載體,所以會(huì)把DTO附上可序列化特性,這此例子中會(huì)使用WCF的數(shù)據(jù)契約實(shí)現(xiàn)OrderDTO和OrderItemDTO。

?

?

如圖,要實(shí)現(xiàn)數(shù)據(jù)轉(zhuǎn)換,就應(yīng)該建立數(shù)據(jù)轉(zhuǎn)換器。在這里OperationAssembler就是一個(gè)數(shù)據(jù)轉(zhuǎn)換器,它是數(shù)據(jù)轉(zhuǎn)換的核心,它是領(lǐng)域?qū)ο笈cDTO之間實(shí)現(xiàn)轉(zhuǎn)換的工具。要在多個(gè)對(duì)象之間實(shí)現(xiàn)數(shù)據(jù)轉(zhuǎn)換實(shí)在是一件非常麻煩的事,所以我一直提倡注意DTO對(duì)象的兼容性,使單個(gè)DTO對(duì)象可以適用于多個(gè)外觀層,以減少數(shù)據(jù)轉(zhuǎn)換所帶來的麻煩。

namespace Business.Service.ApplicationService
{
public class OperationAssembler
{
//把領(lǐng)域?qū)ο筠D(zhuǎn)換成DTO
public static OrderDTO GetOrderDTO(Order order,Person person)
{
OrderDTO orderDTO = new OrderDTO();
if (person != null)
{
orderDTO.EMail = person.EMail.GetString();
orderDTO.Address = person.Address.GetString();
orderDTO.Name = person.Name.GetString();
orderDTO.PersonID = person.ID;
orderDTO.Point = person.Point.GetInt();
orderDTO.Telephone = person.Telephone.GetString();
}
if (order != null)
{
orderDTO.PersonID = order.PersonID;
orderDTO.Count = order.Count.GetInt();
orderDTO.Delivery = order.Delivery.GetDateTime();
orderDTO.Favorable = order.Favorable.GetDouble();
orderDTO.Freightage = order.Freightage.GetDouble();
orderDTO.OrderID = order.ID;
orderDTO.OrderNumber = order.OrderNumber.GetString();
orderDTO.Price = order.Price.GetDouble();
orderDTO.TotalPrice = order.TotalPrice.GetDouble();
var orderItemList = order.OrderItem.ToList();
if (orderItemList.Count != 0)
{
var orderItemDTO = new List<OrderItemDTO>();
foreach (var orderItem in orderItemList)
orderItemDTO.Add(GetOrderItemDTO(orderItem));
orderDTO.OrderItemList = orderItemDTO;
}
}
return orderDTO;
}

public static OrderItemDTO GetOrderItemDTO(OrderItem orderItem)
{
OrderItemDTO orderItemDTO = new OrderItemDTO();
orderItemDTO.Count = orderItem.Count.GetInt();
orderItemDTO.Goods = orderItem.Goods.GetString();
orderItemDTO.OrderID = orderItem.OrderID;
orderItemDTO.OrderItemID = orderItem.ID;
orderItemDTO.Price = orderItem.Price.GetDouble();
return orderItemDTO;
}

//把DTO轉(zhuǎn)換成多個(gè)對(duì)象
public static void SetOrder(OrderDTO orderDTO, out Person person, out Order order)
{
person = new Person();
person.EntityKey=new System.Data.EntityKey("BusinessContext.Person","ID",orderDTO.PersonID);
person.Address = orderDTO.Address;
person.EMail = orderDTO.EMail;
person.ID = orderDTO.PersonID;
person.Name = orderDTO.Name;
person.Point = orderDTO.Point;
person.Telephone = orderDTO.Telephone;

order = new Order();
order.EntityKey=new System.Data.EntityKey("BusinessContext.Order","ID",orderDTO.OrderID);
order.Count = orderDTO.Count;
if (orderDTO.Delivery.Year!=0001&&orderDTO.Delivery.Year!=9999)
order.Delivery = orderDTO.Delivery;
order.Favorable = orderDTO.Favorable;
order.Freightage = orderDTO.Freightage;
order.ID = orderDTO.OrderID;
order.OrderNumber = orderDTO.OrderNumber;
order.PersonID = orderDTO.PersonID;
order.Price = orderDTO.Price;
order.TotalPrice = orderDTO.TotalPrice;
var orderItemDTOList = orderDTO.OrderItemList;
if (orderItemDTOList.Count() != 0)
foreach (var orderItemDTO in orderItemDTOList)
order.OrderItem.Add(GetOrderItem(orderItemDTO));
}

public static OrderItem GetOrderItem(OrderItemDTO orderItemDTO)
{
OrderItem orderItem = new OrderItem();
orderItem.EntityKey = new System.Data.EntityKey("BusinessContext.OrderItem", "ID", orderItemDTO.OrderItemID);
orderItem.Count = orderItemDTO.Count;
orderItem.Goods = orderItemDTO.Goods;
orderItem.ID = orderItemDTO.OrderItemID;
orderItem.OrderID = orderItemDTO.OrderID;
orderItem.Price = orderItemDTO.Price;
return orderItem;
}
}
}

//數(shù)據(jù)傳輸對(duì)象 DTO
namespace Business.TransferObject
{
[DataContract]
public class OrderItemDTO
{
private int _orderItemID;
private int _orderID;
private string _goods;
private double _price;
private int _count;

[DataMember]
public int OrderItemID
{
get { return _orderItemID; }
set { _orderItemID = value; }
}
............
............
}

[DataContract]
public class OrderDTO
{
private int _personID;
private string _name;
private string _address;
private string _telephone;
private int _point;
private string _email;
private int _orderID;
private string _orderNumber;
private int _count;
private double _freightage;
private double _favorable;
private DateTime _delivery;
private double _price;
private double _totalPrice;
private IList<OrderItemDTO> _orderItemDTOList;

[DataMember]
public int PersonID
{
get{return this._personID;}
set{this._personID=value;}
}
..........
..........
}
}

通過數(shù)據(jù)轉(zhuǎn)換器,可以順利實(shí)現(xiàn)領(lǐng)域模型與DTO之間的轉(zhuǎn)換,協(xié)調(diào)應(yīng)用層服務(wù)的運(yùn)行。

4. 應(yīng)用層的發(fā)布

在開發(fā)SOA系統(tǒng)的時(shí)候,應(yīng)用層的服務(wù)需要使用遠(yuǎn)程方法對(duì)外開放,在接收到請(qǐng)求的時(shí)候,它可以調(diào)用領(lǐng)域?qū)臃?wù)獲取運(yùn)算結(jié)果,然后通過數(shù)據(jù)轉(zhuǎn)換器OperationAssembler把運(yùn)算結(jié)果轉(zhuǎn)換成DTO,最后返還到表現(xiàn)層。在起初,我曾嘗試對(duì)應(yīng)每個(gè)應(yīng)用層的對(duì)象建立一個(gè)遠(yuǎn)程接口,但經(jīng)過多次重構(gòu)以后,我覺得行程對(duì)象就是一個(gè)簡單的對(duì)外接口,對(duì)象之間不存在什么邏輯關(guān)系。所以更簡單的方法是使用外觀模式,建立少數(shù)的幾個(gè)遠(yuǎn)程服務(wù)類,把所有的應(yīng)用層對(duì)象的方法都包含在內(nèi)。

?

可以留意代碼,OperationService包括了對(duì)Person模型和Order模型的所有操作。而且每個(gè)操作都只是簡單地調(diào)用應(yīng)用層服務(wù) (ApplicationService) 獲得計(jì)算結(jié)果,然后使用數(shù)據(jù)轉(zhuǎn)換器 (OperationAssembler)轉(zhuǎn)換數(shù)據(jù),當(dāng)中并不存在任何的業(yè)務(wù)邏輯。

namespace Business.Service.ApplicationService
{
[ServiceContract]
public interface IOperationService
{
[OperationContract]
int AddOrder(ref OrderDTO orderDTO);

[OperationContract]
int DeleteOrder(OrderDTO orderDTO);

[OperationContract]
int UpdateOrder(ref OrderDTO orderDTO);

[OperationContract]
IList<OrderDTO> GetOrderByPerson(int personID);

[OperationContract]
OrderDTO GetOrder(int orderID);

[OperationContract]
int AddPerson(ref OrderDTO orderDTO);

[OperationContract]
int UpdatePerson(ref OrderDTO orderDTO);

[OperationContract]
OrderDTO GetPerson(int personID);

[OperationContract]
IList<OrderDTO> GetPersonList();

[OperationContract]
OrderDTO Payment(int orderID);
}

public class OperationService:IOperationService
{
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public int AddOrder(ref OrderDTO orderDTO)
{
OrderService orderService = new OrderService();
Order order = GetOrder(orderDTO);
int n = orderService.AddOrder(order);
orderDTO = OperationAssembler.GetOrderDTO(order, null);
return n;
}

[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public int DeleteOrder(OrderDTO orderDTO)
{
OrderService orderService = new OrderService();
return orderService.DeleteOrder(GetOrder(orderDTO));
}

[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
public int UpdateOrder(ref OrderDTO orderDTO)
{
OrderService orderService = new OrderService();
Order order = GetOrder(orderDTO);
int n = orderService.UpdateOrder(order);
orderDTO = OperationAssembler.GetOrderDTO(order, null);
return n;
}
..............
..............
}
}

回到目錄?

八、系統(tǒng)總體架構(gòu)

1. 體現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的架構(gòu)

到此總結(jié)一下領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)DDD的總體結(jié)構(gòu),Repository層使用ORM映射或SQL命令等方式把持久化數(shù)據(jù)轉(zhuǎn)化為領(lǐng)域?qū)ο?#xff0c;然后根據(jù)業(yè)務(wù)邏輯設(shè)計(jì)對(duì)應(yīng)領(lǐng)域?qū)臃?wù)Domain Service 。接著應(yīng)用層進(jìn)行操作上的協(xié)調(diào),利用Repository、領(lǐng)域模型、領(lǐng)域?qū)臃?wù)Domain Service 完成業(yè)務(wù)需要,再通過數(shù)據(jù)轉(zhuǎn)換器把領(lǐng)域?qū)ο驞omain Object轉(zhuǎn)化為數(shù)據(jù)傳輸對(duì)象DTO。最后,利用遠(yuǎn)程通訊技術(shù)把應(yīng)用層的服務(wù)(Application Service)對(duì)外開放。

注意留意的是SOA系統(tǒng)中,UI表現(xiàn)層與Application Service應(yīng)用層服務(wù)是實(shí)現(xiàn)分離的,表現(xiàn)層可以同時(shí)調(diào)用多方的遠(yuǎn)程服務(wù)來完成工作。

?

?

2. 體現(xiàn)面向服務(wù)開發(fā)的架構(gòu)

面向服務(wù)開發(fā)SOA的架構(gòu)主要體現(xiàn)在表現(xiàn)層與應(yīng)用層之間通過遠(yuǎn)程通訊實(shí)現(xiàn)分離,表現(xiàn)層可以引用多方的應(yīng)用服務(wù)作為基礎(chǔ)。由此系統(tǒng)實(shí)現(xiàn)業(yè)務(wù)上的分離,不同的功能模塊可以獨(dú)立開發(fā),最后通過服務(wù)在表現(xiàn)層共同體現(xiàn)。長期的發(fā)展,使不少的企業(yè)針對(duì)單個(gè)功能模塊開發(fā)出一套獨(dú)立的系統(tǒng),再通過強(qiáng)大的虛擬化技術(shù)為第三方提供服務(wù),這就是云計(jì)算的前身。

就像一個(gè)通訊購物的平臺(tái),其實(shí)就是綜合了內(nèi)部業(yè)務(wù)管理、銀行轉(zhuǎn)帳服務(wù)、呼叫中心、第三方接口等多方服務(wù)的綜合性平臺(tái)。如果你有過這方面的經(jīng)驗(yàn),就會(huì)知道其實(shí)銀行轉(zhuǎn)帳、呼叫中心不過就是銀行、電信、移動(dòng)等公司提供的幾個(gè)簡單的接口。開發(fā)人員根本無需理會(huì)其實(shí)內(nèi)部的結(jié)構(gòu),只要通過幾個(gè)簡單的遠(yuǎn)程方法就能調(diào)用。這正是應(yīng)用層服務(wù) Application Service 的最好體現(xiàn)。

3. 結(jié)束語

寫這篇文章目的只是想與各位分享一下我在開發(fā)過程中的一些體會(huì),歡迎各位點(diǎn)評(píng),指出其中的不足。

其實(shí)架構(gòu)是死物,人才是有腦子的生物。每一個(gè)架構(gòu)必然會(huì)有其優(yōu)點(diǎn),也會(huì)有不足之處,我們應(yīng)該從開發(fā)之中一齊起來體驗(yàn),而不是盲目地跟從,希望在下的拙見能夠給大家?guī)韼椭?蓜e忘了支持一下,挺一挺。

對(duì) .NET 開發(fā)有興趣的朋友歡迎加入QQ群:230564952 共同探討 !

源代碼下載 (數(shù)據(jù)庫可以在.edmx文件根據(jù)模型生成)

回到目錄

?

相關(guān)文章

SOA的概念

SOA基本架構(gòu)

結(jié)合領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的SOA分布式軟件架構(gòu)

作者:風(fēng)塵浪子
http://www.cnblogs.com/leslies2/archive/2011/12/12/2272722.html

原創(chuàng)作品,轉(zhuǎn)載時(shí)請(qǐng)注明作者及出處




轉(zhuǎn)載于:https://www.cnblogs.com/leslies2/archive/2011/12/12/2272722.html

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的结合领域驱动设计的SOA分布式软件架构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。