富領(lǐng)域模型到底長(zhǎng)什么樣兒谢谦?

使用了DDD(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))后释牺,代碼編寫(xiě)有什么不一樣呢萝衩?這可能是程序員們?cè)诮佑|DDD后最關(guān)心的一個(gè)問(wèn)題。這個(gè)系列文章會(huì)對(duì)一些優(yōu)秀的DDD實(shí)例代碼進(jìn)行分析没咙,管中窺豹猩谊,略見(jiàn)數(shù)斑。這是第二篇祭刚。

上一篇文章里通過(guò)分析IDDD_Sample中的領(lǐng)域?qū)哟a占比(90%)和單元測(cè)試代覆蓋率(90%)來(lái)從外部視角感受了富領(lǐng)域模型和我們平時(shí)常用的貧血模型的不同牌捷,感受了富領(lǐng)域模型帶來(lái)的一些好處。

但是上一篇文章結(jié)尾也建議先不要急于實(shí)踐富領(lǐng)域模型涡驮,因?yàn)檫@也是需要具備一些前提條件的暗甥。在了解實(shí)現(xiàn)富領(lǐng)域模型需要什么樣的前提條件之前,我們需要深入地區(qū)了解它捉捅,看看它是什么樣子的撤防,有什么特點(diǎn)。

本篇文章我們會(huì)深入到IDDD_Sample代碼的內(nèi)部棒口,看看富領(lǐng)域模型的代碼是怎么寫(xiě)的寄月,同時(shí)也會(huì)感受到富領(lǐng)域模型帶來(lái)的更多的好處。

人人喜歡白富美

當(dāng)你剛接手一個(gè)已有應(yīng)用時(shí)无牵,了解完這個(gè)應(yīng)用這整個(gè)系統(tǒng)架構(gòu)中所處的位置和所承擔(dān)的職責(zé)后漾肮,就需要去了解這個(gè)應(yīng)用的內(nèi)部實(shí)現(xiàn)。通常是如何入手的呢茎毁?

  • 看文檔
  • 問(wèn)交接給你的人
  • 翻代碼/Debug

這三個(gè)方式一個(gè)比一個(gè)靠譜一些初橘。

  • 文檔可能十分稀少,即使有一些也可能是充滿了謬誤充岛,只能半信半疑;
  • 交接的人好不容易把這爛攤子扔給你耕蝉,棄如敝履崔梗,恨不得永不再碰它,哪有耐心給你講明白垒在,而且可能他也很難講明白蒜魄。如同你新交了一個(gè)女朋友,你希望她的上一任男友把她的一切給你講明白一樣场躯;
  • 那只能自己弄明白谈为,只能一點(diǎn)點(diǎn)去翻代碼,去探索真相踢关。這是唯一靠譜的方法伞鲫,然而這個(gè)過(guò)程很是痛苦,熟悉剛接手的代碼签舞,和熟悉剛接手的女朋友一樣的難秕脓,且漫長(zhǎng)柒瓣;

但你去閱讀 IDDD_Sample的代碼就不會(huì)這樣,因?yàn)樗軉渭兎图埽龥](méi)有心機(jī)芙贫,她毫不隱藏,她胸懷坦露傍药,因?yàn)樗且粋€(gè)“白富美”磺平。

  • “白” - 坦白,從代碼就能看出模型拐辽,不隱藏小秘密拣挪;
  • “富” - 富領(lǐng)域模型,不但擁有屬性薛训,還擁有很多方法媒吗,具有獨(dú)立的人格和行為能力,你很容易知道她有什么和能干什么乙埃;她的社會(huì)關(guān)系也很豐富闸英;
  • “美” - 清晰簡(jiǎn)單就是一種大美,結(jié)構(gòu)之美和邏輯之美介袜;

這樣的女朋友代碼誰(shuí)不喜歡呢甫何?

揭開(kāi)面紗看真容

我們將 com.saasovation.agilepm.domain.model.product.backlogitem 這個(gè)包下面的代碼生成領(lǐng)域模型圖:

backlogitem-domain1.png
backlogitem-domain1.png

我們能獲得以下的這些領(lǐng)域知識(shí):

  • 我們有三個(gè)實(shí)體(BacklogItem,Task遇伞, EstimationLogEntry)
  • 還有四個(gè)值對(duì)象辙喂,比如看到 “BusinessPriority”,就能理解“業(yè)務(wù)優(yōu)先級(jí)”這個(gè)概念
  • 有四個(gè)枚舉鸠珠,比如“StoryPoints” 巍耗,可以知道“故事估算的點(diǎn)數(shù)”這個(gè)概念(0,1渐排,2异雁,3锁蠕,5,8……)

目前,相對(duì)于貧血模型還沒(méi)有太多的優(yōu)勢(shì)拌禾,除了多出的那幾個(gè)值對(duì)象鬓照,能直接顯示一些業(yè)務(wù)概念外弃甥。

讓我們?cè)趫D上展示更多的元素惶室,顯示實(shí)體和值對(duì)象以及枚舉間的關(guān)系。


backlogitem-domain2.png
backlogitem-domain2.png

這時(shí)候我們會(huì)看到帘靡,BacklogItem是一個(gè)聚合根知给,BacklogItem,Task测柠, EstimationLogEntry等是它的子對(duì)象炼鞠,而且一個(gè)BacklogItem下可以有N個(gè)Task……

關(guān)于聚合關(guān)系的定義缘滥,可以通過(guò)UML來(lái)了解

在貧血模型的代碼實(shí)現(xiàn)里,要出現(xiàn)這個(gè)圖是不是需要根據(jù)數(shù)據(jù)庫(kù)外鍵來(lái)推斷谒主,在腦子里畫(huà)出來(lái)呢朝扼?或者維護(hù)在一個(gè)文檔里呢?而對(duì)于富領(lǐng)域模型的代碼霎肯,這個(gè)圖是通過(guò)工具隨時(shí)生成的擎颖。

代碼變化了,圖就會(huì)變化观游,所以這是一個(gè)“活”文檔搂捧。

如果你想了解更多,你可以在圖上展示領(lǐng)域?qū)ο蟮膶傩院头椒ǘ啤A私夥椒ㄒ簿褪撬男袨楹苤匾逝埽悴荒苤豢此撵o態(tài)屬性,比如白皮膚大眼睛搪柑,還要看它睡覺(jué)打不打呼聋丝,流不流哈喇子。

backlogitem-domain3.png
backlogitem-domain3.png

比如BacklogItem里有一個(gè)方法 commitTo(Sprint aSprint) 工碾,從名字上就能看出來(lái)弱睦,一個(gè)BacklogItem是可以提交到一個(gè)Sprint里的。下面是方法的實(shí)現(xiàn)細(xì)節(jié):

public void commitTo(Sprint aSprint) {
        //省略各種校驗(yàn)……

        if (this.isCommittedToSprint()) {
            if (!aSprint.sprintId().equals(this.sprintId())) {
                this.uncommitFromSprint();
            }
        }

        this.elevateStatusWith(BacklogItemStatus.COMMITTED);

        this.setSprintId(aSprint.sprintId());

        DomainEventPublisher
            .instance()
            .publish(new BacklogItemCommitted(
                    this.tenantId(),
                    this.backlogItemId(),
                    this.sprintId()));
    }

前面忘記說(shuō)了渊额,領(lǐng)域模型的代碼里有很多領(lǐng)域事件(比如 BacklogItemCommitted )况木,領(lǐng)域事件也能幫助我們非常好地理解領(lǐng)域知識(shí)。

白富美能當(dāng)飯吃嗎

白富美固然好旬迹,但能當(dāng)飯吃嗎火惊?在領(lǐng)域模型里寫(xiě)了一堆內(nèi)存操作的邏輯,這樣的代碼能有用嗎奔垦?

嗯矗晃,這個(gè)問(wèn)題暴露了我們的階層,我們向往白富美宴倍,又怕養(yǎng)不起,相對(duì)于對(duì)美好生活的向往仓技,我們更擔(dān)心的是餓肚子鸵贬。

放心,能吃飽脖捻,管夠阔逼。下次我們?cè)僬f(shuō)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末地沮,一起剝皮案震驚了整個(gè)濱河市嗜浮,隨后出現(xiàn)的幾起案子羡亩,更是在濱河造成了極大的恐慌,老刑警劉巖危融,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件畏铆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡吉殃,警方通過(guò)查閱死者的電腦和手機(jī)辞居,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蛋勺,“玉大人瓦灶,你說(shuō)我怎么就攤上這事”辏” “怎么了贼陶?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)巧娱。 經(jīng)常有香客問(wèn)我碉怔,道長(zhǎng),這世上最難降的妖魔是什么家卖? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任眨层,我火速辦了婚禮,結(jié)果婚禮上上荡,老公的妹妹穿的比我還像新娘趴樱。我一直安慰自己,他們只是感情好酪捡,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布叁征。 她就那樣靜靜地躺著,像睡著了一般逛薇。 火紅的嫁衣襯著肌膚如雪捺疼。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 50,021評(píng)論 1 291
  • 那天永罚,我揣著相機(jī)與錄音啤呼,去河邊找鬼。 笑死呢袱,一個(gè)胖子當(dāng)著我的面吹牛官扣,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播羞福,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼惕蹄,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起卖陵,我...
    開(kāi)封第一講書(shū)人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤遭顶,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后泪蔫,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體棒旗,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年鸥滨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嗦哆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡婿滓,死狀恐怖老速,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情凸主,我是刑警寧澤橘券,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站卿吐,受9級(jí)特大地震影響旁舰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜嗡官,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一箭窜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧衍腥,春花似錦磺樱、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至尚骄,卻和暖如春块差,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背倔丈。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工憨闰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人需五。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓起趾,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親警儒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容