<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    聽說過「DCI」嗎?

    共 6175字,需瀏覽 13分鐘

     ·

    2023-01-03 00:52

    這里是Z哥的個人公眾號

    每周五11:45 按時送達

    當(dāng)然了,也會時不時加個餐~

    我的第「229」篇原創(chuàng)敬上



    大家好呀,好久不見,我是Z哥。在我最近消失的這段時間里,有些小伙伴微信問我去哪了,老讀者應(yīng)該知道哈,Z哥自從換了工作后的確太忙,打理公眾號的時間都用來加班了。一晃眼,不知不覺都過去4個月了,太慚愧了。 不過最近收獲還挺多的,我接下來慢慢花時間整理出來分享給大家。
    前幾周和團隊里的「DDD」愛好者交流的時候,有人提到了一個概念叫「DCI」。我當(dāng)時就想我只知道「DI」和「CI」,「DCI」又是什么鬼。后來在網(wǎng)上搜了一下才發(fā)現(xiàn)在 2009 年這個概念就被提出來了,當(dāng)時的文章是《The DCI Architecture: A New Vision of Object-Oriented Programming》。
    DCI 中的 3 個字母分別代表:Data,Context,Interactive。在我看來,這 3 個概念共同配合表達出了某個“角色”做的事情:
    「誰/什么東西(Data)」-「在什么場景下(Context)」-「做什么事(Interactive)」
    比如,當(dāng)你在家里打掃衛(wèi)生的時候,你的角色其實是“清潔工”;當(dāng)你在家里燒飯的時候,你的角色是“廚師”;當(dāng)你在家里運動的時候,你的角色是“運動者”。你看,同樣的一個人在不同場景下所產(chǎn)生的行為都與當(dāng)時所處的角色有關(guān)。
    DCI 的核心就是那個 Interactive,也是“角色”這個概念存在的地方。


    我們來舉個例子看看它的作用。 就拿前面提到的例子來看,如果我們只是識別出其中的實體是 Person,那么自然打掃衛(wèi)生的方法 Clean(),以及燒飯的方法 Cook(),和運動的方法 Exercise()自然而然就落到了 Person 這個實體上。那么問題就來了,一個人在社會生活中需要做的事情有很多,如果按照這個思路,Person 這個實體將成為一個上帝類。
          
            func?(p?Person)?Clean()?{
          
          
              fmt.Println("Clean")
          
          
            }
          
          
            
              
    func (p Person) CookFood() { fmt.Println("CookFood") }
    func (p Person) Sport() { fmt.Println("Sport") }
    type Person struct { Name string Age int }


    同時,如果有某個領(lǐng)域服務(wù)或者實體上的方法以 Person 作為參數(shù),那么其內(nèi)部將可以任意調(diào)用 Clean()、Cook() 或者 Exercise()。
          
            func MethodA(p Person){
          
          
              p.Clean()
          
          
              p.CookFood()
          
          
              p.Sport()
          
          
            }
          
        
    這很明顯與 OO 思想中的核心概念「高內(nèi)聚低耦合」背道而馳,違反了「迪米特法則」。
    而函數(shù)式編程的三層架構(gòu)之所以流行了很多年,就是因為它的世界里主要關(guān)注的是顆粒度最小的「方法」應(yīng)該放到三層中的哪一層,而對「方法」在某一層內(nèi)放到哪個對象之中是沒有明確規(guī)定的。 因此在上面的例子中,如果我們將Clean()、Cook() 和 Exercise() 分別寫在不同的 XXXService 中,并同時接收 Person 作為入?yún)ⅲ敲纯梢暂p松地消除“上帝類”,但與此同時 Person 也成為了一個只有屬性的「貧血模型」。 因此 DCI 的提出就是通過一個新的視角來定義對象,它通過增加一層概念——「角色」,將傳統(tǒng) DDD 中對象上的非通用方法轉(zhuǎn)移到了不同的角色對象中,避免了需要在一個對象上同時表達“是什么”和“能做什么”而可能出現(xiàn)的「上帝類」問題。 同時,通過由多個角色組成的對象也避免了「貧血模型」的發(fā)生。
    接下來看看如何使用 DCI 來重新設(shè)計上面的代碼。其實很簡單,將 Person 設(shè)計成由 3 個角色 Cleaner、Cook、Sporter 組成,在每個角色中分別定義 Clean()、Cook() 和 Exercise()方法。
          
            type Cleaner interface {
          
          
              Clean()
          
          
            }
          
          
            
              
    type Cook interface { CookFood() }
    type Sporter interface { Sport() }
    type Person struct { Name string Age int }
    func (p Person) Clean() { fmt.Println("Clean") }
    func (p Person) CookFood() { fmt.Println("CookFood") }
    func (p Person) Sport() { fmt.Println("Sport") }
    func DoSomeThing(cook Cook) { fmt.Println("DoSomeThing") cook.CookFood() }
    func main() { ??var?p?Person p.Clean() p.CookFood() p.Sport() DoSomeThing(p) }
    如此一來,我們可以將一些使用 Person 作為入?yún)⒌姆椒ㄕ{(diào)整成相應(yīng)的角色,以達到「迪米特法則」所提倡的效果。

    我們再想深入一步,Cook() 和 Clean() 的實現(xiàn)中都需要“拿起東西”,這是一個和角色無關(guān)的行為,那么可以將它直接定義在Person中。
          
            func (p Person) TakeUp(thing string) {
          
          
              fmt.Println(fmt.Sprintf("%s TakeUp a %s", p.Name, thing))
          
          
            }
          
          
            
              
    func (p Person) Clean() { p.TakeUp("掃帚") fmt.Println("Clean") }
    func (p Person) CookFood() { p.TakeUp("鍋子") fmt.Println("CookFood") }
    在 DCI 中,將角色上定義的方法稱作「Role Method」,將對象(Data)上定義的方法稱作「Local Method」。 前者是填充業(yè)務(wù)邏輯的地方,而后者更像是對象(Data)自身天然具有的能力,與業(yè)務(wù)邏輯無關(guān)。
    上面的這整套實現(xiàn)邏輯在 DCI 中被稱作 Methodless Role,與之對應(yīng)的還有 Methodful Role 的實現(xiàn)邏輯,在這里就不展開了。顧名思義就是在角色的定義上更豐富,將「Local Method」也定義出來。另外,增加一層「角色」的概念后,我們可以發(fā)現(xiàn),任何具有相同行為的對象都可以給他設(shè)置同一個角色。比如,機器人也可以打掃,那么這個 Cleaner 的角色也可以定義到 Robot 對象中,而不僅僅是 Person 對象。只不過,Robot.Clean() 的實現(xiàn)不是“拿起掃帚”,而是“制定一個行走路線”,然后它自己會把垃圾吸到自己身體里。
    可能你會問,Context 呢?好像一直沒提到它該怎么實現(xiàn)?以 Z 哥目前的理解來看,Context 所做的事情其實和傳統(tǒng) DDD 中的 Applicaion 層做的事情是重合的,只是代碼結(jié)構(gòu)的不同。因此,我認(rèn)為這部分倒不是重點,你可以按照原先的 Application 層代碼來寫,相當(dāng)于每一個 Application 層中的方法就是一個 Context。
    本質(zhì)上說,DCI 是一種 “角色接口” 設(shè)計思想,如果習(xí)慣 OO 編程的小伙伴應(yīng)該是很熟悉這種寫法的。
    好了,我們總結(jié)一下。這篇呢,Z哥和你分享了我對 DCI 的了解。它通過引入「角色」的概念,將傳統(tǒng) DDD 建模時賦予「對象」的兩個職責(zé)“是什么”和“能做什么”中的后者拆分到「角色」中去定義,避免上帝類問題。同時,因為角色最終還是會作用到「對象」上,所以也不會出現(xiàn)函數(shù)式編程中的貧血模型問題。DCI 中,對定義在「角色」上的方法稱為 Role Method,而直接定義在「對象」上的方法稱作 Local Method。對于「角色」在編碼的實現(xiàn),一般建議使用 interface 的方式來體現(xiàn),因為“角色只定義行為”,具體行為要怎么做,由所在的對象來實現(xiàn)。如此符合「依賴倒置原則」的場景自然適合用 interface 來實現(xiàn)。
    最后,Z 哥再分享一個實踐 DCI 的思路給你。首先是什么時候需要用 DCI?當(dāng)你在實踐 DDD 的過程中,覺得某個對象過大了,有點上帝類的味道,這時候就可以想一下是否可以通過 DCI 來重新設(shè)計一下。如何落地DCI?分為以下四步:
    1. 識別領(lǐng)域場景

    2. 羅列其中的業(yè)務(wù)行為

    3. 分析這些定位屬于什么角色,定義角色接口

    4. 確定承擔(dān)這些角色的數(shù)據(jù)對象,定義數(shù)據(jù)類以及數(shù)據(jù)類的本地方法


    好了,今天就聊這些,希望對你有所啟發(fā)。


    推薦閱讀:


    原創(chuàng)不易,如果你覺得這篇文章還不錯,就「 點贊 」或者「在看」一下吧,鼓勵我的創(chuàng)作 :)


    也可以分享我的公眾號名片給有需要的朋友們。


    如果你有關(guān)于軟件架構(gòu)、分布式系統(tǒng)、產(chǎn)品、運營的困惑

    可以試試點擊「閱讀原文

    瀏覽 55
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報
    評論
    圖片
    表情
    推薦
    點贊
    評論
    收藏
    分享

    手機掃一掃分享

    分享
    舉報

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    国产AV影视 | 婷婷无码成人精品俺来俺去 | 亚洲天堂女人 | 国产美女日逼视频 | 免费看A片18 的视频 |