0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何實(shí)現(xiàn)DCI架構(gòu)(中)

jf_78858299 ? 來源:元閏子的邀請(qǐng) ? 作者:元閏子 ? 2023-05-10 17:10 ? 次閱讀

然而,充血模型并非完美,它也有很多問題,比較典型的是這兩個(gè):

問題一:上帝類

People這個(gè)實(shí)體包含了太多的職責(zé),導(dǎo)致它變成了一個(gè)名副其實(shí)的上帝類。試想,這里還是裁剪了很多“人”所包含的屬性和行為,如果要建模一個(gè)完整的模型,其屬性和方法之多,無(wú)法想象。 上帝類違反了單一職責(zé)原則,會(huì)導(dǎo)致代碼的可維護(hù)性變得極差 。

問題二:模塊間耦合

SchoolCompany本應(yīng)該是相互獨(dú)立的,School不必關(guān)注上班與否,Company也不必關(guān)注考試與否。但是現(xiàn)在因?yàn)樗鼈兌家蕾嚵?code>People這個(gè)實(shí)體,School可以調(diào)用與Company相關(guān)的Work()OffWork()方法,反之亦然。這導(dǎo)致 模塊間產(chǎn)生了不必要的耦合,違反了接口隔離原則

這些問題都是工程派不能接受的,從軟件工程的角度,它們會(huì)使得代碼難以維護(hù)。解決這類問題的方法,比較常見的是對(duì)實(shí)體進(jìn)行拆分,比如將實(shí)體的行為建模成 領(lǐng)域服務(wù) ,像這樣:

type People struct {
 vo.IdentityCard
 vo.StudentCard
 vo.WorkCard
 vo.Account
}

type StudentService struct{}
func (s *StudentService) Study(p *entity.People) {
 fmt.Printf("Student %+v studying\\n", p.StudentCard)
}
func (s *StudentService) Exam(p *entity.People) {
 fmt.Printf("Student %+v examing\\n", p.StudentCard)
}

type WorkerService struct{}
func (w *WorkerService) Work(p *entity.People) {
 fmt.Printf("%+v working\\n", p.WorkCard)
 p.Account.Balance++
}
func (w *WorkerService) OffWOrk(p *entity.People) {
 fmt.Printf("%+v getting off work\\n", p.WorkCard)
}

// ...

圖片

這種建模方法,解決了上述兩個(gè)問題,但也變成了所謂的 貧血模型People變成了一個(gè)純粹的數(shù)據(jù)類,沒有任何業(yè)務(wù)行為。在人的心理上,這樣的模型并不能在建立起對(duì)現(xiàn)實(shí)世界的對(duì)應(yīng)關(guān)系,不容易讓人理解,因此被學(xué)院派所抵制。

到目前為止,貧血模型和充血模型都有各有優(yōu)缺點(diǎn),工程派和學(xué)院派誰(shuí)都無(wú)法說服對(duì)方。接下來,輪到本文的主角出場(chǎng)了。

DCI架構(gòu)

DCI (Data,Context,Interactive)架構(gòu)是一種面向?qū)ο蟮能浖軜?gòu)模式,在《The DCI Architecture: A New Vision of Object-Oriented Programming》一文中被首次提出。與傳統(tǒng)的面向?qū)ο笙啾?,DCI能更好地對(duì)數(shù)據(jù)和行為之間的關(guān)系進(jìn)行建模,從而更容易被人理解。

  • Data ,也即數(shù)據(jù)/領(lǐng)域?qū)ο?,用來描述系統(tǒng)“是什么”,通常采用DDD中的戰(zhàn)術(shù)建模來識(shí)別當(dāng)前模型的領(lǐng)域?qū)ο螅韧贒DD分層架構(gòu)中的領(lǐng)域?qū)印?/li>
  • Context ,也即場(chǎng)景,可理解為是系統(tǒng)的Use Case,代表了系統(tǒng)的業(yè)務(wù)處理流程,等同于DDD分層架構(gòu)中的應(yīng)用層。
  • Interactive ,也即交互,是DCI相對(duì)于傳統(tǒng)面向?qū)ο蟮淖畲蟀l(fā)展,它認(rèn)為我們應(yīng)該顯式地對(duì)領(lǐng)域?qū)ο螅?Object )在每個(gè)業(yè)務(wù)場(chǎng)景(Context)中扮演( Cast )的角色( Role )進(jìn)行建模。 Role代表了領(lǐng)域?qū)ο笤跇I(yè)務(wù)場(chǎng)景中的業(yè)務(wù)行為(“做什么”),Role之間通過交互完成完整的義務(wù)流程

這種角色扮演的模型我們并不陌生,在現(xiàn)實(shí)的世界里也是隨處可見,比如,一個(gè)演員可以在這部電影里扮演英雄的角色,也可以在另一部電影里扮演反派的角色。

DCI認(rèn)為,對(duì)Role的建模應(yīng)該是面向Context的,因?yàn)樘囟ǖ臉I(yè)務(wù)行為只有在特定的業(yè)務(wù)場(chǎng)景下才會(huì)有意義。通過對(duì)Role的建模,我們就能夠?qū)㈩I(lǐng)域?qū)ο蟮姆椒ú鸱殖鋈?,從而避免了上帝類的出現(xiàn)。最后,領(lǐng)域?qū)ο笸ㄟ^組合或繼承的方式將Role集成起來,從而具備了扮演角色的能力。

圖片

DCI架構(gòu)一方面通過角色扮演模型使得領(lǐng)域模型易于理解,另一方面通過“ 小類大對(duì)象 ”的手法避免了上帝類的問題,從而較好地解決了貧血模型和充血模型之爭(zhēng)。另外,將領(lǐng)域?qū)ο蟮男袨楦鶕?jù)Role拆分之后,模塊更加的高內(nèi)聚、低耦合了。

使用DCI建模

回到前面的案例,使用DCI的建模思路,我們可以將“人”的幾種行為按照不同的角色進(jìn)行劃分。吃完、睡覺、玩游戲,是作為人類角色的行為;學(xué)習(xí)、考試,是作為學(xué)生角色的行為;上班、下班,是作為員工角色的行為;購(gòu)票、游玩,則是作為游玩者角色的行為?!叭恕痹?strong>家這個(gè)場(chǎng)景中,充當(dāng)?shù)氖侨祟惖慕巧辉?strong>學(xué)校這個(gè)場(chǎng)景中,充當(dāng)?shù)氖菍W(xué)生的角色;在公司這個(gè)場(chǎng)景中,充當(dāng)?shù)氖菃T工的角色;在公園這個(gè)場(chǎng)景中,充當(dāng)?shù)氖怯瓮嬲叩慕巧?/p>

圖片

需要注意的是,學(xué)生、員工、游玩者,這些角色都應(yīng)該具備人類角色的行為,比如在學(xué)校里,學(xué)生也需要吃飯。

最后,根據(jù)DCI建模出來的模型,應(yīng)該是這樣的:

圖片

在DCI模型中,People不再是一個(gè)包含眾多屬性和方法的“上帝類”,這些屬性和方法被拆分到多個(gè)Role中實(shí)現(xiàn),而People由這些Role組合而成。

另外,SchoolCompany也不再耦合,School只引用了Student,不能調(diào)用與Company相關(guān)的WorkerWork()OffWorker()方法。

圖片

代碼實(shí)現(xiàn)DCI模型

DCI建模后的代碼目錄結(jié)構(gòu)如下;

- context: 場(chǎng)景
  - company.go
  - home.go
  - park.go
  - school.go
- object: 對(duì)象
  - people.go
- data: 數(shù)據(jù)
  - account.go
  - identity_card.go
  - student_card.go
  - work_card.go
- role: 角色
  - enjoyer.go
  - human.go
  - student.go
  - worker.go

從代碼目錄結(jié)構(gòu)上看,DDD和DCI架構(gòu)相差并不大,aggregate目錄演變成了context目錄;vo目錄演變成了data目錄;entity目錄則演變成了objectrole目錄。

首先,我們實(shí)現(xiàn)基礎(chǔ)角色Human,StudentWorker、Enjoyer都需要組合它:

package role

// 人類角色
type Human struct {
 data.IdentityCard
 data.Account
}
func (h *Human) Eat() {
 fmt.Printf("%+v eating\\n", h.IdentityCard)
 h.Account.Balance--
}
func (h *Human) Sleep() {
 fmt.Printf("%+v sleeping\\n", h.IdentityCard)
}
func (h *Human) PlayGame() {
 fmt.Printf("%+v playing game\\n", h.IdentityCard)
}

接著,我們?cè)賹?shí)現(xiàn)其他角色,需要注意的是, Student、WorkerEnjoyer不能直接組合Human ,否則People對(duì)象將會(huì)有4個(gè)Human子對(duì)象,與模型不符:

// 錯(cuò)誤的實(shí)現(xiàn)
type Worker struct {
 Human
}
func (w *Worker) Work() {
 fmt.Printf("%+v working\\n", w.WorkCard)
 w.Balance++
}
...
type People struct {
 Human
 Student
 Worker
 Enjoyer
}
func main() {
 people := People{}
  fmt.Printf("People: %+v", people)
}
// 結(jié)果輸出, People中有4個(gè)Human:
// People: {Human:{} Student:{Human:{}} Worker:{Human:{}} Enjoyer:{Human:{}}}
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    DCI 顛覆光器件產(chǎn)業(yè)?

    從不成熟到成熟的推進(jìn)劑,但是DCI肯定要為此付出一點(diǎn)代價(jià)!關(guān)于技術(shù)架構(gòu)DCI早先采用一種分布式架構(gòu)。但是不知道為什么DCI現(xiàn)在熱衷CWDM
    發(fā)表于 02-08 15:53

    Xilinx FPGA DCI使用方法

    各位大神,請(qǐng)問Xilinx FPGADCI是如何使用的?我知道是把每個(gè)Bank的VRP、VRN管腳分別下拉、上拉,除此之外,在HDL代碼和約束應(yīng)該如何寫呢?查了半天資料沒有查到,所以來論壇問問。@LQVSHQ
    發(fā)表于 08-20 20:51

    DDR3控制器和SSTL15_T_DCI在同一個(gè)bank

    你好,我使用Virtex7的HP庫(kù)來實(shí)現(xiàn)DDR3控制器。我的控制器將以1600Mbps的速度運(yùn)行,因此主控制器的VRN和VRP應(yīng)連接一個(gè)80Ω電阻,以實(shí)現(xiàn)更高的性能。實(shí)現(xiàn)addr /
    發(fā)表于 03-25 11:04

    為什么銀行也沒有DCI匹配?

    在ml_605的示意圖中,我發(fā)現(xiàn)在一個(gè)銀行(例如銀行16)混合了LVDS信號(hào)和信號(hào)端信號(hào),所以銀行應(yīng)該收起2.5v,并且銀行有DCI匹配。但是在銀行24(銀行混合了LVDS信號(hào)和信號(hào)端信號(hào)),所以
    發(fā)表于 10-25 08:47

    如何在IBIS文件配置SSTL135 DCI阻抗

    用作輸入時(shí)并聯(lián)施加GND和PWR設(shè)置?如何為我的電路板設(shè)計(jì)中使用的較低DCI阻抗正確配置IBIS文件?有人建議在設(shè)計(jì)添加外部終端電阻以進(jìn)行仿真。但是,對(duì)于這些雙向線路,DCI僅在充當(dāng)輸入時(shí)才有效。那些外部電阻會(huì)在輸出期間產(chǎn)生負(fù)
    發(fā)表于 07-14 09:10

    DCI是什么?Xilinx 7系列FPGA的HP bank都支持DCI

    Xilinx 7系列FPGA的HP bank都支持DCI,目的是在高速單板信號(hào)傳輸中保持信號(hào)完整性,減少反射等因素影響,那么DCI是什么?digitally controlled impedance
    發(fā)表于 06-27 09:11 ?1.9w次閱讀
    <b class='flag-5'>DCI</b>是什么?Xilinx 7系列FPGA的HP bank都支持<b class='flag-5'>DCI</b>

    一種AUTOSAR軟件架構(gòu)RTE的實(shí)現(xiàn)方法

    介紹了一種AUTOSAR軟件架構(gòu)RTE的實(shí)現(xiàn)方法。
    發(fā)表于 07-13 16:02 ?6次下載

    DCI BOX與傳統(tǒng)WDM/OTN設(shè)備有什么區(qū)別?

    DCI-BOX,中國(guó)聯(lián)通叫模塊化波分設(shè)備,中國(guó)電信叫盒式波分設(shè)備DCI-BOX,是數(shù)據(jù)中心點(diǎn)到點(diǎn)互連(DCI)的設(shè)備。在DCI BOX出現(xiàn)之前,DC
    的頭像 發(fā)表于 03-26 14:29 ?1701次閱讀

    DCI BOX與傳統(tǒng)WDM/OTN設(shè)備有什么區(qū)別?

    DCI BOX出現(xiàn)之前,DCI通常使用WDM/OTN設(shè)備進(jìn)行互連,那么兩者之間有什么區(qū)別呢?
    的頭像 發(fā)表于 03-27 15:37 ?1080次閱讀

    易飛揚(yáng)全新升級(jí)DCI BOX,照亮DCI傳輸網(wǎng)絡(luò)

    易飛揚(yáng)2U 6.4T DCI BOX
    的頭像 發(fā)表于 04-14 17:46 ?1097次閱讀
    易飛揚(yáng)全新升級(jí)<b class='flag-5'>DCI</b> BOX,照亮<b class='flag-5'>DCI</b>傳輸網(wǎng)絡(luò)

    易飛揚(yáng)非相干DCI BOX的DCI傳輸方案介紹

    易飛揚(yáng)推出的最新1U 800G DWDM DCI BOX是一款1U盒式的多業(yè)務(wù)波分傳輸平臺(tái),可滿足最大8×100GE業(yè)務(wù)點(diǎn)對(duì)點(diǎn)傳輸?shù)膽?yīng)用場(chǎng)景,單機(jī)框常規(guī)接入容量800G。它同樣滿足DCI對(duì)小體積、低功耗、極簡(jiǎn)維護(hù)、低時(shí)延、大帶寬的需求。
    發(fā)表于 04-21 10:39 ?499次閱讀

    非相干DCI BOX,提供更經(jīng)濟(jì)的DCI傳輸方案

    易飛揚(yáng)推出的最新1U 800G DWDM DCI BOX是一款1U盒式的多業(yè)務(wù)波分傳輸平臺(tái),可滿足最大8×100GE業(yè)務(wù)點(diǎn)對(duì)點(diǎn)傳輸?shù)膽?yīng)用場(chǎng)景,單機(jī)框常規(guī)接入容量800G。它同樣滿足DCI對(duì)小體積、低功耗、極簡(jiǎn)維護(hù)、低時(shí)延、大帶寬的需求。
    的頭像 發(fā)表于 04-21 10:40 ?839次閱讀

    非相干DCI BOX,提供更經(jīng)濟(jì)的DCI傳輸方案

    上文,我們介紹了相干DCI BOX完美適配目前DCI傳輸?shù)膽?yīng)用,不過,相干子系統(tǒng)的成本向來比較高,那是否有成本較低的非相干設(shè)備可供選擇?考慮到不同用戶的預(yù)算需求,易飛揚(yáng)同樣提供經(jīng)濟(jì)型的非相干DCI BOX,本文介紹的1U 800
    的頭像 發(fā)表于 04-24 09:46 ?828次閱讀
    非相干<b class='flag-5'>DCI</b> BOX,提供更經(jīng)濟(jì)的<b class='flag-5'>DCI</b>傳輸方案

    如何實(shí)現(xiàn)DCI架構(gòu)(上)

    在面向?qū)ο缶幊痰睦砟罾?,?yīng)用程序是對(duì)現(xiàn)實(shí)世界的抽象,我們經(jīng)常會(huì)將現(xiàn)實(shí)的事物建模為編程語(yǔ)言中的類/對(duì)象(“ **是什么** ”),而事物的行為則建模為方法(“ **做什么** ”)。面向?qū)ο缶幊逃?/div>
    的頭像 發(fā)表于 05-10 17:09 ?663次閱讀
    如何<b class='flag-5'>實(shí)現(xiàn)</b><b class='flag-5'>DCI</b><b class='flag-5'>架構(gòu)</b>(上)

    如何實(shí)現(xiàn)DCI架構(gòu)(下)

    在面向?qū)ο缶幊痰睦砟罾?,?yīng)用程序是對(duì)現(xiàn)實(shí)世界的抽象,我們經(jīng)常會(huì)將現(xiàn)實(shí)的事物建模為編程語(yǔ)言中的類/對(duì)象(“ **是什么** ”),而事物的行為則建模為方法(“ **做什么** ”)。面向?qū)ο缶幊逃?/div>
    的頭像 發(fā)表于 05-10 17:10 ?566次閱讀