色尼玛亚洲综合影院,亚洲3atv精品一区二区三区,麻豆freexxxx性91精品,欧美在线91

領(lǐng)域模型管理與AOP

  英文原文:ASPects of Domain Model Management

  (作者:Mats Helander,譯者:王麗娟)

  2007-12-23

  導(dǎo)言

  正如從像《領(lǐng)域驅(qū)動設(shè)計(jì)》[Evans DDD]和《領(lǐng)域驅(qū)動設(shè)計(jì)和模式應(yīng)用[Nilsson ADDDP]這些書中學(xué)到的一樣,在應(yīng)用架構(gòu)中引入領(lǐng)域模型模式(《企業(yè)應(yīng)用架構(gòu)模式》[Fowler PoEAA])一定會有很多益處,但是它們并不是無代價的。

  使用領(lǐng)域模型,很少會像創(chuàng)建實(shí)際領(lǐng)域模型類、然后使用它們那么簡單。很快你就會發(fā)現(xiàn),領(lǐng)域模型必須得到相當(dāng)數(shù)量的基礎(chǔ)架構(gòu)代碼的支持。

  領(lǐng)域模型所需基礎(chǔ)架構(gòu)當(dāng)中最顯著的當(dāng)然是持久化——通常是持久化到關(guān)系型數(shù)據(jù)庫中,也就是對象/關(guān)系(O/R)映射出場的地方。但是,情況并不止持久化那么簡單。在一個復(fù)雜的應(yīng)用中,用來在運(yùn)行時管理領(lǐng)域模型對象的部分占了基礎(chǔ)架構(gòu)的很大一部分。我將基礎(chǔ)架構(gòu)的這部分稱為領(lǐng)域模型管理(Domain Model Management)[Helander DMM],或簡稱為DMM。

  基礎(chǔ)架構(gòu)代碼放在哪里?

  隨著基礎(chǔ)架構(gòu)代碼的增長,找到一個處理它的優(yōu)良架構(gòu)變得越來越重要。問題主要在于——我們是否允許把一些基礎(chǔ)架構(gòu)代碼放在我們的領(lǐng)域模型類里面,還是無論如何應(yīng)該避免這樣做?

  避免基礎(chǔ)架構(gòu)代碼進(jìn)入領(lǐng)域模型類的論點(diǎn)是強(qiáng)有力的:領(lǐng)域模型應(yīng)該表示應(yīng)用程序所處理的核心業(yè)務(wù)概念。對于想大量使用其領(lǐng)域模型的應(yīng)用來說,保持這些類干凈、輕量級、易于維護(hù)是一個極好的架構(gòu)目標(biāo)。

  另一方面,我們接下來將會看到,保持領(lǐng)域模型類完全不含基礎(chǔ)架構(gòu)代碼——通常被稱為使用POJO/POCO(Plain Old Java/CLR Objects)領(lǐng)域模型,這種極端的路線也被證明是有問題的。最終往往導(dǎo)致采用笨重的、低效率的變通方法來解決問題——而且有些功能用這種方式根本不可能實(shí)現(xiàn)。

  也就是說,我們遇到的還是一個權(quán)衡利弊的情況,我們應(yīng)該盡量在領(lǐng)域模型類里面只放必不可少的基礎(chǔ)架構(gòu)代碼,決不超出這個限度。我們付出領(lǐng)域模型的輕微發(fā)胖,換來效率的提高以及使一些必要領(lǐng)域模型管理功能有可能實(shí)現(xiàn)。畢竟,軟件架構(gòu)很大程度上是關(guān)于如何做一筆好買賣。

  重構(gòu)的時機(jī)到了

  不幸的是,長遠(yuǎn)看來,臺面上的交易條件可能不夠好。為了支持許多最有用和最強(qiáng)大的功能,你需要在領(lǐng)域模型類中放入基礎(chǔ)架構(gòu)代碼實(shí)在太多了。其數(shù)量之大,很可能你的系統(tǒng)還沒完成,業(yè)務(wù)邏輯代碼就已經(jīng)被淹沒了。

  也就是說,除非我們能找到一種方法魚和熊掌兼得。本文試圖分析我們能否找到這樣一種方式,既能將必要的基礎(chǔ)架構(gòu)代碼分布到領(lǐng)域模型中,卻又不會使領(lǐng)域模型類變得雜亂。

  我們先從一個應(yīng)用看起,它將所有有關(guān)的基礎(chǔ)架構(gòu)代碼都放到了領(lǐng)域模型類中。接著我們將重構(gòu)這個應(yīng)用,并且只用眾所周知的、可靠的、真正面向?qū)ο蟮脑O(shè)計(jì)模式,使應(yīng)用最后能具備相同的功能,但是基礎(chǔ)架構(gòu)代碼卻不會弄亂領(lǐng)域模型類。最后,我們將看看我們?nèi)绾问褂妹嫦蚍矫婢幊蹋?a href=/itjie/ASPjishu/ target=_blank class=infotextkey>ASPect Oriented Programming,AOP)來更簡單地達(dá)到相同的效果。

  但是,為了看出AOP為何能幫助我們處理DMM需求,我們首先看看沒有AOP的時候我們的代碼會是什么樣——首先是“最原始”的形式,這種形式里,所有的基礎(chǔ)架構(gòu)代碼都放在領(lǐng)域模型類里面,然后是重構(gòu)后的形式,其中基礎(chǔ)架構(gòu)代碼已經(jīng)被分離出領(lǐng)域模型類——雖然仍然分布在領(lǐng)域模型中!

  重構(gòu)肥領(lǐng)域模型

  大部分的領(lǐng)域模型運(yùn)行時管理是基于攔截的——也就是說,當(dāng)你在代碼中訪問領(lǐng)域模型對象時,你所有對對象的訪問都會根據(jù)相應(yīng)功能的需要被攔截下來。

  一個明顯的例子就是臟跟蹤(dirty tracking。它可以用于應(yīng)用的很多部分,以了解一個對象什么時候已經(jīng)被修改了、但是仍未保存(它處于“臟”狀態(tài))。用戶界面可以利用該信息提醒用戶是否打算放棄任何未保存的修改,而持久化機(jī)制則可以利用它來辨明哪些對象是真正需要被保存到持久化介質(zhì)中的,從而避免保存所有的對象。

  臟跟蹤的一種方法是保持領(lǐng)域?qū)ο笞畛醯摹⑽葱薷陌姹镜目截悾⒃诿看蜗胫酪粋€對象是否已經(jīng)被修改的時候去比較它們。這個方案的問題是既浪費(fèi)內(nèi)存,又慢。一個更有效率的方法是攔截對領(lǐng)域?qū)ο髎etter方法的調(diào)用,以便每當(dāng)調(diào)用對象的一個setter方法的時候,都為該對象設(shè)置一個臟標(biāo)記。

  臟標(biāo)記放在哪里?

  現(xiàn)在我們來看看把臟標(biāo)記放在哪里的問題。一種是將它放在一個字典結(jié)構(gòu)中,對象和標(biāo)記分別作為鍵和值。這樣做的問題在于,我們必須讓程序中所有需要它的部分都能訪問到這個字典。前面的例子已經(jīng)可以看出,需要訪問字典的包括用戶界面和持久化機(jī)制這樣截然不同的部分。


圖 1

  將字典放在這些組件的任何一個內(nèi)部,都會使其它組件難以訪問它。在分層結(jié)構(gòu)中,底層不能調(diào)用其上層(除了中心領(lǐng)域模型,它常常處于一個公共的、垂直的層里面,能被其它所有的層調(diào)用),因此要么把字典放在需要訪問它的最低一層(圖1),要么放在公共的、垂直的層里面(圖2)。兩種選擇都不是很有吸引力,因?yàn)樗鹆?a href=/pingce/yingyong/ target=_blank class=infotextkey>應(yīng)用組件間不必要的耦合和不均衡的責(zé)任分配。


圖 2

  一個更吸引人的、順應(yīng)面向?qū)ο笏枷氲倪x擇,是將臟標(biāo)記放到領(lǐng)域?qū)ο蟊旧碇腥ィ@樣每個領(lǐng)域?qū)ο蠖紟в幸粋€布爾型的臟屬性,來表明它是不是臟的(圖3)。這樣,任何組件想知道一個領(lǐng)域?qū)ο笈K與否,可以直接問它。


圖 3

  因此,我們把部分基礎(chǔ)架構(gòu)功能代碼放在領(lǐng)域模型中,其部分原因就是我們希望從應(yīng)用的不同部分都能擁有這些功能,而不會過度地增強(qiáng)耦合。用戶界面部分不該知道如何向持久化組件詢問臟標(biāo)志,并且,我們寧愿在分層的應(yīng)用架構(gòu)中設(shè)計(jì)盡可能少的垂直層。

  這個理由很重要,單憑它就足以讓一些人考慮采納本文將要檢驗(yàn)的這種方法,不過我們還是先看看其他方法。但是在這樣做之前,我們先粗略地看一下爭論的另一方——我們在領(lǐng)域模型類中限制基礎(chǔ)架構(gòu)代碼的原因。

  肥領(lǐng)域模型反模式

  讓我們看看,引入臟標(biāo)記、并在適當(dāng)時機(jī)要求攔截喚醒臟標(biāo)記之后,領(lǐng)域類會是什么樣子。這是一個C#代碼的例子。

public class Person : IDirty
{
protected string name;
public virtual string Name
{
get { return name; }
set
{
if (value != name)
((IDirty)this).Dirty = true;
name = value;
}
}

private bool dirty;
bool IDirty.Dirty
{
get { return dirty; }
set { dirty = value; }
}
}

public interface IDirty
{
bool Dirty { get; set; }
}

it知識庫領(lǐng)域模型管理與AOP,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 濮阳县| 嘉祥县| 津南区| 四川省| 定州市| 西乌珠穆沁旗| 河池市| 讷河市| 东兰县| 金门县| 谢通门县| 南开区| 海安县| 阳谷县| 凤山市| 平遥县| 临沭县| 江都市| 塔河县| 全椒县| 冕宁县| 鹤壁市| 台山市| 准格尔旗| 四会市| 秭归县| 酉阳| 聂拉木县| 渑池县| 潞城市| 富顺县| 阿拉尔市| 岑溪市| 兴海县| 全椒县| 凤冈县| 八宿县| 博湖县| 武山县| 当涂县| 阿图什市|