自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

DDD 中的幾個(gè)困難問題

原創(chuàng) 精選
開發(fā)
通俗來說,領(lǐng)域就是業(yè)務(wù)知識。業(yè)務(wù)有一些內(nèi)在規(guī)則,存在專業(yè)性,比如財(cái)務(wù)、CRM、OA、電商等不同領(lǐng)域的業(yè)務(wù)規(guī)則不同。計(jì)算機(jī)只是業(yè)務(wù)規(guī)則的自動化。更加具體來說,構(gòu)成領(lǐng)域的要素就是特定的業(yè)務(wù)場景。

作者 | 林寧

?領(lǐng)域到底是什么?

對領(lǐng)域這個(gè)詞的理解就是 DDD 入門的第一個(gè)難關(guān)。我們有時(shí)會被客戶問到,領(lǐng)域到底是什么?首先要清晰地知道領(lǐng)域是什么,才能劃分核心域、支撐域和通用域。換句話說,構(gòu)成領(lǐng)域的要素是什么呢?

領(lǐng)域是一個(gè)非常抽象的詞匯,我們需要先對其具象化。在英語的語境中,“Domain” 其實(shí)就是業(yè)務(wù),指的是現(xiàn)實(shí)生活中的各種事務(wù)。處理稅務(wù)、記賬、售貨記錄等,這些都是領(lǐng)域。

于是,我們給領(lǐng)域下了一個(gè)定義:

領(lǐng)域(Domain)是業(yè)務(wù)相關(guān)知識的集合。

通俗來說,領(lǐng)域就是業(yè)務(wù)知識。業(yè)務(wù)有一些內(nèi)在規(guī)則,存在專業(yè)性,比如財(cái)務(wù)、CRM、OA、電商等不同領(lǐng)域的業(yè)務(wù)規(guī)則不同。計(jì)算機(jī)只是業(yè)務(wù)規(guī)則的自動化。更加具體來說,構(gòu)成領(lǐng)域的要素就是特定的業(yè)務(wù)場景。

通過對業(yè)務(wù)的場景劃分,再對其分類,就是我們的子域。

  • 核心域:那些對業(yè)務(wù)極其重要的場景,內(nèi)容社區(qū)應(yīng)用,就是提問、看帖、回復(fù)。
  • 支撐域:那些對重要業(yè)務(wù)支持的場景,比如登錄、找回密碼等場景。
  • 通用域:那些已經(jīng)成為相對獨(dú)立的支撐業(yè)務(wù)場景,比如實(shí)名驗(yàn)證、人機(jī)校驗(yàn)(以前是支撐,現(xiàn)在可以是通用)。

領(lǐng)域和上下文是什么關(guān)系?

如果領(lǐng)域的構(gòu)成要件是場景,上下文的構(gòu)成要件是模型,那么領(lǐng)域和上下文之間就沒有包含和被包含關(guān)系。

也不存在一個(gè)領(lǐng)域是否對應(yīng)多個(gè)上下文的關(guān)系。

他們構(gòu)成:上下文支撐領(lǐng)域的關(guān)系,領(lǐng)域?qū)С錾舷挛牡年P(guān)系。

DDD 軟件建模就是業(yè)務(wù)問題和解決方案之間的橋梁。領(lǐng)域是問題,設(shè)計(jì)出來的模型是解的一部分。因此,問題和解形如 x 和 f(x) 的關(guān)系,f = 軟件建模過程。

舉個(gè)例子來說,某個(gè)電商網(wǎng)站有多個(gè)渠道,零售、批發(fā)、企業(yè)采購等多個(gè)場景的業(yè)務(wù),這是他們的領(lǐng)域。對于研發(fā)工程師來說,他們會最終設(shè)計(jì)出訂單、商品等模型上下文,來支持這些領(lǐng)域。

聚合如何持久化?

聚合被賦予了兩個(gè)責(zé)任:

  • 負(fù)責(zé)業(yè)務(wù)的一致性。?
  • 負(fù)責(zé)數(shù)據(jù)的整體存儲。?

而其持久化是一個(gè)老大難問題。

關(guān)于業(yè)務(wù)的一致性,Eric DDD 給我們描述了一種理想情景。只要把業(yè)務(wù)一致的一組模型從數(shù)據(jù)庫中統(tǒng)一獲取到,對其做業(yè)務(wù)修改,然后再持久化回去,就可以避免業(yè)務(wù)的一致性被破壞。

業(yè)務(wù)的一致性可以這樣理解。我們有訂單和訂單項(xiàng),訂單的總價(jià)由訂單項(xiàng)計(jì)算得來。如果不長眼的程序員把訂單項(xiàng)直接修改了,而不更新訂單,就會帶來 bug。

但是,遺憾的是我們的內(nèi)存不是無限大,而且數(shù)據(jù)會在斷電后丟失。我們必須把數(shù)據(jù)從磁盤中讀取出來,而磁盤的訪問速度很慢。數(shù)據(jù)在磁盤中的組織形式使用了集合+關(guān)聯(lián)的方式存放,這是由于我們?yōu)榱私档蛿?shù)據(jù)冗余和方便查詢而不得已為之。這就是關(guān)系模型和對象模型的差異,而不得不采用一些技術(shù)方法轉(zhuǎn)換(ORM)。

而數(shù)據(jù)的整體存儲,讓聚合的持久化變得困難和性能低下。

一個(gè)簡單的道理是,我們只需要一個(gè)橘子,卻總想把橘子樹搬來搬去,雖然摘橘子需要通過橘子樹。

充血模型為什么不符合編程習(xí)慣?

充血模型已經(jīng)是很多 DDD 實(shí)踐者的潛在認(rèn)知,簡單來說就是把業(yè)務(wù)行為放到模型中。

這種做法看似滿足了面向?qū)ο蟮膶?shí)踐,但是在實(shí)際工作中,它并不方便,甚至有些別扭。在培訓(xùn)中,有學(xué)員找我們說,學(xué)了 DDD 之后不會寫代碼了,甚至忘記之前的代碼該如何編寫。

極端一點(diǎn)的例子,還會有人在聚合根中調(diào)用倉儲來實(shí)現(xiàn)聚合的存儲。這時(shí),他們發(fā)現(xiàn)矛盾在于 JPA 的存儲需要使用實(shí)體的類型信息,這時(shí)候便束手無策了。

在辯證唯物主義認(rèn)識論中,一個(gè)行為構(gòu)成的要件是:主體 + 動詞 + 客體。

在英語學(xué)習(xí)中,主謂賓結(jié)構(gòu)的主體是主語,客體就是賓語。甚至,主系表結(jié)構(gòu)也滿足這個(gè)道理。主語是主體,表語是主體的屬性,也是客體。

“太陽是圓的”。指的是,太陽的形狀是圓的。太陽是主體,“是” 作為邏輯謂詞可以認(rèn)為是動詞,“圓的”是太陽的外觀屬性。

合適的充血模型是給 “主體”充血,給客體貧血。特殊的情況是,當(dāng)一個(gè)模型操作它的屬性的時(shí)候,它也可以是主體。因此,給領(lǐng)域模型的操作能力,應(yīng)該僅限于操作自己的屬性。而領(lǐng)域模型的構(gòu)建、業(yè)務(wù)處理、持久化應(yīng)該交給主體來做。

一個(gè)有意思的悖論就是,不合適的充血模型就像讓一張桌子讓它自己把自己搬到樓上去,我們難描述這種行為。更好的做法不是去找一個(gè)搬運(yùn)工去搬這個(gè)桌子么,這次行為的主體就是搬運(yùn)工,客體就是這個(gè)桌子。

如何清晰的分層?

分層有兩個(gè)原則:

  • 分層是有明確目的,沒有目的的分層會帶來額外的問題。?
  • 分層需要考慮框架、庫的實(shí)現(xiàn),否則容易帶了 “千層餅架構(gòu)”。?

分層的目的為了隔離差異,沒有差異而進(jìn)行的分層就是浪費(fèi)。由于差異的出現(xiàn),每層所對應(yīng)的客體就發(fā)生了變化。

  • 接入層:處理接入?yún)f(xié)議,這個(gè)時(shí)候還不知道領(lǐng)域信息,客體就是數(shù)據(jù)包的不同形式。?
  • 應(yīng)用層:處理業(yè)務(wù)場景,比如用戶注冊、添加用戶、導(dǎo)入用戶等,客體就是一些用例對象。?
  • 領(lǐng)域?qū)樱禾幚硗ㄓ妙I(lǐng)域能力,比如創(chuàng)建用戶,客體主要就是領(lǐng)域模型。?
  • 技術(shù)設(shè)施層:為上層提供技術(shù)實(shí)現(xiàn),并不知道領(lǐng)域?qū)拥男畔?。比?JPA 是一種持久化實(shí)現(xiàn),需要從領(lǐng)域?qū)虞斎雽ο蟮念愋托畔⒑蛿?shù)據(jù)信息,客體就是泛型對象。?

多對多關(guān)系一般怎么處理?

多對多就是客體的含混不清,迷失了中間模型。

一個(gè)訂單可以有多個(gè)商品,實(shí)際上是一個(gè)訂單有多個(gè)訂單項(xiàng)。

  • 一個(gè)用戶可以加入多個(gè)文檔協(xié)作編輯,實(shí)際上是一個(gè)用戶可以成為多個(gè)文檔的參與人。?
  • 一個(gè)用戶可以加入多個(gè)用戶組,實(shí)際上是一個(gè)用戶可以在多個(gè)用戶組成為成員。?

辨明客體,可以讓代碼變得清晰、簡單、解耦。在現(xiàn)實(shí)中,一個(gè)老板可以有多個(gè)公司,一個(gè)公司也可以由多個(gè)老板投資。他們之間的多對多關(guān)系是通過 “股東” 這個(gè)客體來承載的。

在有限責(zé)任的公司中,股東身份和老板的個(gè)人身份(自然人)相互獨(dú)立,并得到司法支持。?

責(zé)任編輯:趙寧寧 來源: Thoughtworks洞見
相關(guān)推薦

2009-03-23 10:25:22

JavaOracle應(yīng)用開發(fā)

2021-12-04 23:17:32

元宇宙區(qū)塊鏈VR

2009-02-11 09:22:19

JavaJava開發(fā)Oracle應(yīng)用

2015-04-28 11:19:15

C++ C++分析 C++問題

2025-01-26 10:10:30

2011-07-04 16:40:39

QT 串口 QML

2010-08-11 09:21:37

2021-10-12 00:04:24

腳本備份MariDB

2010-03-08 19:03:23

Python腳本

2015-11-18 19:08:21

創(chuàng)業(yè)困難

2010-07-12 13:00:49

UML建模

2022-04-06 07:32:41

Java運(yùn)算符變量

2020-11-06 13:09:59

的機(jī)器學(xué)習(xí)

2011-07-25 16:13:34

SQL Server數(shù)據(jù)挖掘

2023-07-04 08:09:05

數(shù)據(jù)庫選型集中式

2023-02-20 14:44:22

DDD領(lǐng)域模型

2021-05-20 08:51:33

設(shè)計(jì)驅(qū)動數(shù)據(jù)庫

2024-05-31 12:59:03

2019-01-07 14:36:36

Go系統(tǒng)開源庫

2011-03-08 10:58:09

Sybase數(shù)據(jù)庫
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號