<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          談?wù)劥a:降低復(fù)雜度,從放棄三層架構(gòu)到DDD入門

          共 5714字,需瀏覽 12分鐘

           ·

          2021-08-09 09:51

          本文首發(fā)于泊浮目的簡書:www.jianshu.com/u/204b8aaab…

          版本日期備注
          1.02021.8.1文章首發(fā)

          1.前言

          最近我發(fā)現(xiàn)團(tuán)隊(duì)項(xiàng)目中的某個(gè)應(yīng)用復(fù)雜度越來越高,具體表現(xiàn)為:

          • 代碼可讀性較差:各個(gè)服務(wù)之間調(diào)用復(fù)雜,流程不清晰

          • 修改部分業(yè)務(wù)導(dǎo)致大量測(cè)試用例失敗,但很難快速的尋找出這些測(cè)試用例失敗的根因

          基于這些情況,我開始尋找降低復(fù)雜度的方案,于是就有了這篇再談DDD的文章。

          1.1 具體問題

          1.1.1 宏觀角度

          從宏觀來說,軟件架構(gòu)模式演進(jìn)經(jīng)歷了三個(gè)階段。

          • 第一階段是單機(jī)架構(gòu):采用面向過程的設(shè)計(jì)方法,系統(tǒng)包括客戶端 UI 層和數(shù)據(jù)庫兩層,采用 C/S 架構(gòu)模式,整個(gè)系統(tǒng)圍繞數(shù)據(jù)庫驅(qū)動(dòng)設(shè)計(jì)和開發(fā),并且總是從設(shè)計(jì)數(shù)據(jù)庫和字段開始。

          • 第二階段是集中式架構(gòu):采用面向?qū)ο蟮脑O(shè)計(jì)方法,系統(tǒng)包括業(yè)務(wù)接入層、業(yè)務(wù)邏輯層和數(shù)據(jù)庫層,采用經(jīng)典的三層架構(gòu),也有部分應(yīng)用采用傳統(tǒng)的 SOA 架構(gòu)。這種架構(gòu)容易使系統(tǒng)變得臃腫,可擴(kuò)展性和彈性伸縮性差。

          • 第三階段是分布式微服務(wù)架構(gòu):隨著微服務(wù)架構(gòu)理念的提出,集中式架構(gòu)正向分布式微服務(wù)架構(gòu)演進(jìn)。微服務(wù)架構(gòu)可以很好地實(shí)現(xiàn)應(yīng)用之間的解耦,解決單體應(yīng)用擴(kuò)展性和彈性伸縮能力不足的問題。我們知道,在單機(jī)和集中式架構(gòu)時(shí)代,系統(tǒng)分析、設(shè)計(jì)和開發(fā)往往是獨(dú)立、分階段割裂進(jìn)行的。

          比如,在系統(tǒng)建設(shè)過程中,我們經(jīng)常會(huì)看到這樣的情形:A 負(fù)責(zé)提出需求,B 負(fù)責(zé)需求分析,C 負(fù)責(zé)系統(tǒng)設(shè)計(jì),D 負(fù)責(zé)代碼實(shí)現(xiàn),這樣的流程很長,經(jīng)手的人也很多,很容易導(dǎo)致信息丟失。最后,就很容易導(dǎo)致需求、設(shè)計(jì)與代碼實(shí)現(xiàn)的不一致,往往到了軟件上線后,我們才發(fā)現(xiàn)很多功能并不是自己想要的,或者做出來的功能跟自己提出的需求偏差太大。

          而且在單機(jī)和集中式架構(gòu)這兩種模式下,軟件無法快速響應(yīng)需求和業(yè)務(wù)的迅速變化,最終錯(cuò)失發(fā)展良機(jī)。此時(shí),分布式微服務(wù)的出現(xiàn)就有點(diǎn)恰逢其時(shí)的意思了。

          上面這部分來自于極客時(shí)間,這里面指出一般DDD是使用在微服務(wù)設(shè)計(jì)與拆分上,但我認(rèn)為在單體應(yīng)用中做模塊的拆分也是可以并推薦的,這可以讓你的模塊在需要時(shí)可以即刻拆分出去——變成一個(gè)獨(dú)立的微服務(wù)。相關(guān)可以參考【ZStack】4.進(jìn)程內(nèi)服務(wù),這是一個(gè)開源,并實(shí)施于生產(chǎn)中很好的一個(gè)案例。

          1.1.2 微觀角度

          這個(gè)問題很簡單,service的代碼必然會(huì)越堆越多,而且聚攏越來越多的業(yè)務(wù)。

          2.DDD入門

          我們先來看一張圖:

          從最外層開始——什么是領(lǐng)域?大白話來說就是一系列問題的聚合。舉個(gè)例子:

          • 電商平臺(tái)中的電商域,你要解決的一系列問題有:

            • 用戶認(rèn)證

            • 移動(dòng)收付

            • 訂單

            • 報(bào)價(jià)

            • ...

          可以看到,域是呈現(xiàn)出來的是一系列的業(yè)務(wù)領(lǐng)域問題。

          在不同域中,同一個(gè)數(shù)據(jù)實(shí)體的抽象形態(tài)往往是不同的。比如,Bookstore 應(yīng)用中的書本,在銷售領(lǐng)域中關(guān)注的是價(jià)格,在倉儲(chǔ)領(lǐng)域中關(guān)注的是庫存數(shù)量,在商品展示領(lǐng)域中關(guān)注的是書籍的介紹信息。

          2.1 上下文邊界

          往里面,我們應(yīng)該看到的是限界上下文。其實(shí)這個(gè)翻譯并不好,原文叫bounded context,叫做上下文邊界更為妥當(dāng)。本質(zhì)上來說,它定義了邊界。再具體點(diǎn),即:用來封裝通用語言和領(lǐng)域?qū)ο?,提供上下文環(huán)境,保證在領(lǐng)域之內(nèi)的一些術(shù)語、業(yè)務(wù)相關(guān)對(duì)象等(通用語言)有一個(gè)確切的含義,沒有二義性。

          2.2 聚合

          接下來,我們看到了聚合。聚合就是由業(yè)務(wù)和邏輯緊密關(guān)聯(lián)的實(shí)體和值對(duì)象組合而成的,聚合是數(shù)據(jù)修改和持久化的基本單元,每一個(gè)聚合對(duì)應(yīng)一個(gè)倉儲(chǔ),實(shí)現(xiàn)數(shù)據(jù)的持久化。

          聚合有一個(gè)聚合根和上下文邊界,這個(gè)邊界根據(jù)業(yè)務(wù)單一職責(zé)和高內(nèi)聚原則,定義了聚合內(nèi)部應(yīng)該包含哪些實(shí)體和值對(duì)象,而聚合之間的邊界是松耦合的。按照這種方式設(shè)計(jì)出來的微服務(wù)很自然就是“高內(nèi)聚、低耦合”的。

          那聚合根是什么呢?

          聚合根的主要目的是為了避免由于復(fù)雜數(shù)據(jù)模型缺少統(tǒng)一的業(yè)務(wù)規(guī)則控制,而導(dǎo)致聚合、實(shí)體之間數(shù)據(jù)不一致性的問題。

          傳統(tǒng)數(shù)據(jù)模型中的每一個(gè)實(shí)體都是對(duì)等的,如果任由實(shí)體進(jìn)行無控制地調(diào)用和數(shù)據(jù)修改,很可能會(huì)導(dǎo)致實(shí)體之間數(shù)據(jù)邏輯的不一致。而如果采用鎖的方式則會(huì)增加軟件的復(fù)雜度,也會(huì)降低系統(tǒng)的性能。

          如果把聚合比作組織,那聚合根就是這個(gè)組織的負(fù)責(zé)人。聚合根也稱為根實(shí)體,它不僅是實(shí)體,還是聚合的管理者。

          首先它作為實(shí)體本身,擁有實(shí)體的屬性和業(yè)務(wù)行為,實(shí)現(xiàn)自身的業(yè)務(wù)邏輯。

          其次它作為聚合的管理者,在聚合內(nèi)部負(fù)責(zé)協(xié)調(diào)實(shí)體和值對(duì)象按照固定的業(yè)務(wù)規(guī)則協(xié)同完成共同的業(yè)務(wù)邏輯。

          最后在聚合之間,它還是聚合對(duì)外的接口人,以聚合根 ID 關(guān)聯(lián)的方式接受外部任務(wù)和請(qǐng)求,在上下文內(nèi)實(shí)現(xiàn)聚合之間的業(yè)務(wù)協(xié)同。也就是說,聚合之間通過聚合根 ID 關(guān)聯(lián)引用,如果需要訪問其它聚合的實(shí)體,就要先訪問聚合根,再導(dǎo)航到聚合內(nèi)部實(shí)體,外部對(duì)象不能直接訪問聚合內(nèi)實(shí)體。

          2.3 實(shí)體與值對(duì)象

          在 DDD 中有這樣一類對(duì)象,它們擁有唯一標(biāo)識(shí)符,且標(biāo)識(shí)符在歷經(jīng)各種狀態(tài)變更后仍能保持一致。對(duì)這些對(duì)象而言,重要的不是其屬性,而是其延續(xù)性和標(biāo)識(shí),對(duì)象的延續(xù)性和標(biāo)識(shí)會(huì)跨越甚至超出軟件的生命周期。我們把這樣的對(duì)象稱為實(shí)體。其實(shí)很像數(shù)據(jù)庫里自帶不變id的一行行業(yè)務(wù)數(shù)據(jù)。

          值對(duì)象相對(duì)不是那么重要,因?yàn)樗怯脕砻枋鰧?shí)體的一組屬性集。很多系統(tǒng)中的實(shí)現(xiàn)會(huì)以json來實(shí)現(xiàn),比如【ZStack】7.標(biāo)簽系統(tǒng)。

          為了方便理解,這邊做個(gè)小結(jié)。實(shí)體和值對(duì)象的目的都是抽象聚合若干屬性以簡化設(shè)計(jì)和溝通,有了這一層抽象,我們?cè)谑褂萌藛T實(shí)體時(shí),不會(huì)產(chǎn)生歧義,在引用地址值對(duì)象時(shí),不用列舉其全部屬性,在同一個(gè)限界上下文中,大幅降低誤解、縮小偏差,兩者的區(qū)別如下:

          1. 兩者都經(jīng)過屬性聚類形成,實(shí)體有唯一性,值對(duì)象沒有。在本文案例的限界上下文中,人員有唯一性,一旦某個(gè)人員被系統(tǒng)納入管理,它就被賦予了在事件、流程和操作中被唯一識(shí)別的能力,而值對(duì)象沒有也不必具備唯一性。

          2. 實(shí)體著重唯一性和延續(xù)性,不在意屬性的變化,屬性全變了,它還是原來那個(gè)它;值對(duì)象著重描述性,對(duì)屬性的變化很敏感,屬性變了,它就不是那個(gè)它了(意味著不可變性,它可能是從外部查詢來的)。

          3. 戰(zhàn)略上的思考框架穩(wěn)定不變,戰(zhàn)術(shù)上的模型設(shè)計(jì)卻靈活多變,實(shí)體和值對(duì)象也有可能隨著系統(tǒng)業(yè)務(wù)關(guān)注點(diǎn)的不同而更換位置。比如,如果換一個(gè)特殊的限界上下文,這個(gè)上下文更關(guān)注地址,而不那么關(guān)注與這個(gè)地址產(chǎn)生聯(lián)系的人員,那么就應(yīng)該把地址設(shè)計(jì)成實(shí)體,而把人員設(shè)計(jì)成值對(duì)象。

          3. DDD上手

          3.1 從三層模型到DDD

          這里先簡單介紹一下三層模型到DDD對(duì)應(yīng)的一個(gè)變化。

          可以的看得出來,主要是對(duì)service進(jìn)行了拆分。一般可以拆成三層:

          • 應(yīng)用服務(wù)層:多個(gè)領(lǐng)域服務(wù)或外部應(yīng)用服務(wù)進(jìn)行封裝、編排和組合,對(duì)外提供粗粒度的服務(wù)。應(yīng)用服務(wù)主要實(shí)現(xiàn)服務(wù)組合和編排,是一段獨(dú)立的業(yè)務(wù)邏輯。

          • 領(lǐng)域服務(wù)層:由多個(gè)實(shí)體組合而成,一個(gè)方法可能會(huì)跨實(shí)體進(jìn)行調(diào)用。在代碼過于復(fù)雜的時(shí)候,可以將每個(gè)領(lǐng)域服務(wù)拆分為一個(gè)領(lǐng)域服務(wù)類,而不是將所有領(lǐng)域服務(wù)代碼放到一個(gè)領(lǐng)域服務(wù)類中。

          • 實(shí)體:是一個(gè)充血模型。同一個(gè)實(shí)體相關(guān)的邏輯都在實(shí)體類代碼中實(shí)現(xiàn)。

          3.2 建模簡介

          我們可以用三步來劃定領(lǐng)域模型和微服務(wù)的邊界。

          • 第一步:在事件風(fēng)暴中梳理業(yè)務(wù)過程中的用戶操作、事件以及外部依賴關(guān)系等,根據(jù)這些要素梳理出領(lǐng)域?qū)嶓w等領(lǐng)域?qū)ο蟆?/p>

          • 第二步:根據(jù)領(lǐng)域?qū)嶓w之間的業(yè)務(wù)關(guān)聯(lián)性,將業(yè)務(wù)緊密相關(guān)的實(shí)體進(jìn)行組合形成聚合,同時(shí)確定聚合中的聚合根、值對(duì)象和實(shí)體。在第二章的圖里,聚合之間的邊界是第一層邊界,它們?cè)谕粋€(gè)微服務(wù)實(shí)例中運(yùn)行,這個(gè)邊界是邏輯邊界,所以用虛線表示。

          • 第三步:根據(jù)業(yè)務(wù)及語義邊界等因素,將一個(gè)或者多個(gè)聚合劃定在一個(gè)限界上下文內(nèi),形成領(lǐng)域模型。在第二章的圖里,限界上下文之間的邊界是第二層邊界,這一層邊界可能就是未來微服務(wù)的邊界,不同限界上下文內(nèi)的領(lǐng)域邏輯被隔離在不同的微服務(wù)實(shí)例中運(yùn)行,物理上相互隔離,所以是物理邊界,邊界之間用實(shí)線來表示。

          3.3 實(shí)踐:設(shè)計(jì)一個(gè)MiniStack

          為了便于大家理解,我在這里會(huì)設(shè)計(jì)一個(gè)很簡單的Iaas平臺(tái),并在里面代入最基本的DDD概念。

          3.3.1 產(chǎn)品愿景

          • 為了:企業(yè)的內(nèi)部的開發(fā)者、運(yùn)維人員

          • 他們的:計(jì)算、存儲(chǔ)、網(wǎng)絡(luò)資源管理

          • 這個(gè):MiniStack

          • 是一個(gè):私有云平臺(tái)

          • 它可以:管理計(jì)算、存儲(chǔ)、網(wǎng)絡(luò)資源管理,幫用戶簡單快速的創(chuàng)建虛擬機(jī)

          • 而不像:OpenStack

          • 我們的產(chǎn)品:簡單、健壯、智能

          串起來就是:為了滿足企業(yè)的內(nèi)部的開發(fā)者和運(yùn)維人員,他們的硬件資源管理,我們建設(shè)里這個(gè)MiniStack,它是一個(gè)私有云平臺(tái),它可以管理計(jì)算、存儲(chǔ)、網(wǎng)絡(luò)資源管理,幫用戶簡單快速的創(chuàng)建虛擬機(jī),而不像OpenStack,我們的產(chǎn)品簡單、健壯、彈性。

          3.3.2 場景分析

          因篇幅原因,我們來聊個(gè)最典型的場景——?jiǎng)?chuàng)建虛擬機(jī),以便理出相關(guān)的領(lǐng)域模型。

          在這里我們需要注意,我們要盡可能的梳理整個(gè)系統(tǒng)發(fā)生的操作、命令、領(lǐng)域時(shí)間以及依賴變化等。

          3.3.2.1 創(chuàng)建虛擬機(jī)

          1. 用戶登陸系統(tǒng):從數(shù)據(jù)庫中對(duì)信息進(jìn)行校驗(yàn),完成登陸認(rèn)證

          2. 創(chuàng)建虛擬機(jī):填寫虛擬機(jī)名、集群、計(jì)算規(guī)格、L3網(wǎng)絡(luò)以及鏡像。如果需要的話(簡單的體現(xiàn)),可以指定所在的物理機(jī)、以及網(wǎng)段。

            • VM服務(wù)需要提供創(chuàng)建虛擬機(jī)接口

          3. 提交至MiniStack引擎,引起開始做相關(guān)調(diào)度:

            • VM服務(wù)需要提供啟動(dòng)接口

            • 物理機(jī)服務(wù)需要提供拉取鏡像接口

            • 網(wǎng)絡(luò)服務(wù)需要提供IP分配接口

            • 物理機(jī)服務(wù)需要提供查詢接口

            1. 尋找符合計(jì)算、存儲(chǔ)資源的低負(fù)載物理機(jī),并更新vm所屬的物理機(jī)

            2. 分配L3網(wǎng)絡(luò)中的空閑IP,并更新vm相關(guān)的網(wǎng)絡(luò)信息

            3. 告訴物理機(jī)agent:從鏡像服務(wù)器拉取鏡像到第1步尋找出的物理機(jī)

            4. 告訴物理機(jī)agent啟動(dòng)參數(shù),拉起vm

          4. 界面上返回創(chuàng)建成功,用戶可以看到vm

          但創(chuàng)建完虛擬機(jī)以后并不是就這么完事了,萬一哪天這臺(tái)物理機(jī)carsh了呢?哪天CPU因?yàn)槠婀值倪M(jìn)程而打滿了呢?因此為了我們的目標(biāo)——智能,創(chuàng)建vm后,MiniStac每5分鐘收集一系列的監(jiān)控信息:

          1. 向物理機(jī)agent發(fā)送心跳包,確保物理機(jī)狀態(tài)正常

          2. 向虛擬機(jī)agent發(fā)送心跳包,并會(huì)返回:計(jì)算、存儲(chǔ)、網(wǎng)絡(luò)的相關(guān)狀態(tài)

          3.3.3 宏觀設(shè)計(jì):領(lǐng)域建模

          在這一步,我們需要對(duì)業(yè)務(wù)進(jìn)行分析,建立領(lǐng)域模型。一般步驟為:

          1. 找出領(lǐng)域?qū)嶓w和值對(duì)象等領(lǐng)域?qū)ο?/p>

          2. 找出聚合根,根據(jù)實(shí)體、值對(duì)象與聚合根的依賴關(guān)系,建立聚合

          3. 第三步根據(jù)業(yè)務(wù)及語義邊界等因素,定義限界上下文

          3.3.3.1 定義實(shí)體

          我們大致可以找出幾個(gè)實(shí)體:

          • 虛擬機(jī)

            • 啟動(dòng)

            • 停止

          • 物理機(jī)的存儲(chǔ)資源

            • 查詢

            • 分配

            • 釋放

          • 物理機(jī)的計(jì)算資源

            • 查詢

            • 分配

            • 釋放

          • L3網(wǎng)絡(luò)

            • 分配IP

          • 鏡像服務(wù)器

            • 查詢鏡像

            • 添加鏡像

            • 發(fā)布鏡像

          3.3.3.2 定義聚合與限界上下文

          在找聚合前,我們先要找出聚合根??梢苑譃槲锢頇C(jī)、網(wǎng)絡(luò)、鏡像服務(wù)器、虛擬機(jī)。而他們彼此都是獨(dú)立的上下文,在需要的情況下,也可以拆成一個(gè)個(gè)微服務(wù),如果是單體應(yīng)用,則建議用模塊手段進(jìn)行邏輯隔離。

          3.3.4 微觀:領(lǐng)域?qū)ο笈c代碼結(jié)構(gòu)分析

          當(dāng)我們完成宏觀上的建模后,便可以開始做微觀的事:梳理微服務(wù)內(nèi)的領(lǐng)域?qū)ο?,梳理領(lǐng)域?qū)ο笾g的關(guān)系,確定它們?cè)诖a模型和分層架構(gòu)中的位置,建立領(lǐng)域模型與微服務(wù)模型的映射關(guān)系,以及服務(wù)之間的依賴關(guān)系。

          大致上,分位兩步:

          1. 分析領(lǐng)域?qū)ο?/p>

          2. 設(shè)計(jì)代碼結(jié)構(gòu)

          3.3.4.1  分析領(lǐng)域?qū)ο?/h4>

          在這一步,我們需要確認(rèn):

          • 服務(wù)的分層

          • 應(yīng)用服務(wù)由哪些服務(wù)組成

          • 領(lǐng)域服務(wù)包含哪些實(shí)體和實(shí)體方法

          • 哪個(gè)實(shí)體是聚合根

          • 實(shí)體有哪些屬性和方法

          • 哪些對(duì)象為值對(duì)象

          由于我們的用例比較簡單,整理如下:

          • 應(yīng)用服務(wù):

            • VM創(chuàng)建服務(wù):負(fù)責(zé)創(chuàng)建VM,會(huì)調(diào)度大量的底層領(lǐng)域服務(wù)

          • 領(lǐng)域服務(wù):VM服務(wù)、物理機(jī)服務(wù)、網(wǎng)絡(luò)服務(wù)、鏡像服務(wù)

            • VM服務(wù):管理VM的生命周期,如創(chuàng)建、刪除、啟動(dòng)、停止等

            • 物理機(jī)服務(wù):物理機(jī)相關(guān)服務(wù),如添加、刪除、狀態(tài)變更、心跳感知、資源RUD等

            • 網(wǎng)絡(luò)服務(wù):網(wǎng)絡(luò)相關(guān)服務(wù),如創(chuàng)建刪除L2、L3網(wǎng)絡(luò),IP管理等

            • 鏡像服務(wù):鏡像服務(wù)器相關(guān)服務(wù),如添加、刪除、狀態(tài)變更、增加鏡像等

          • 實(shí)體:VM實(shí)體、物理機(jī)實(shí)體、本地存儲(chǔ)實(shí)體(物理機(jī)存儲(chǔ))

            • VM實(shí)體:啟動(dòng)、停止等

            • 物理機(jī)實(shí)體:狀態(tài)變更、心跳感知等

            • L3實(shí)體:IP段添加、刪除、IP分配、釋放等

            • 本地存儲(chǔ)實(shí)體:存儲(chǔ)的占用與釋放

          接下來看一下聚合中的對(duì)象,我們把及格聚合根識(shí)別出來:

          • 物理機(jī)聚合的中的聚合根是物理機(jī)

          • 網(wǎng)絡(luò)聚合中的聚合根是L2網(wǎng)絡(luò)

          • 鏡像聚合中的聚合根是鏡像服務(wù)器

          • 虛擬機(jī)聚合中的聚合根是虛擬機(jī)實(shí)體

          而上面提到的實(shí)體屬性與方法我們已經(jīng)在圖中呈現(xiàn)出來了。

          關(guān)于值對(duì)象,可以參考【ZStack】7.標(biāo)簽系統(tǒng)。該設(shè)計(jì)用于真實(shí)生產(chǎn)中。

          3.3.4.2  設(shè)計(jì)代碼結(jié)構(gòu)

          當(dāng)我們完成領(lǐng)域?qū)ο蟮姆治龊螅覀儽汩_始設(shè)計(jì)各領(lǐng)域?qū)ο笤诖a模型中的呈現(xiàn)方式了——即建立領(lǐng)域?qū)ο笈c代碼對(duì)象的映射關(guān)系。根據(jù)這種映射關(guān)系,服務(wù)人員可以快速定位到業(yè)務(wù)邏輯所在的代碼位置。

          宏觀上,我們可以參考以下分層模型:

          微觀實(shí)施上,我們可以參考COLA。

          4.小結(jié)

          本文和大家一起捋了一遍DDD,并在文里“憑空的”設(shè)計(jì)了一個(gè)項(xiàng)目。其實(shí)這個(gè)項(xiàng)目并非憑空,我參考了以前參與的開源項(xiàng)目ZStack并對(duì)它做出了簡化——該項(xiàng)目目前跑在大量的企業(yè)用戶的私有云中,迭代已有6年多。因此無論從設(shè)計(jì)還是落地來說,都有一定的參考經(jīng)驗(yàn)。

          為了大家方便將文中的例子結(jié)合ZStack代碼理解,我這邊做了一個(gè)映射。

          4.1 參考資料

          • 關(guān)于ZStack的資料

            • 【ZStack】4.進(jìn)程內(nèi)服務(wù)

            • 【ZStack】7.標(biāo)簽系統(tǒng)

            • 【ZStack】9.查詢API

            • ZStack源碼剖析:如何在百萬行代碼中快速迭代

            • ZStack源碼剖析之設(shè)計(jì)模式鑒賞——三駕馬車

            • ZStack Github Repo

          • 雖然ZStack是個(gè)值得參考的項(xiàng)目,但其DDD的設(shè)計(jì)并不是特別明顯。因此在項(xiàng)目分層上也可以參考COLA

          • 《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》



          作者:泊浮目
          鏈接:https://juejin.cn/post/6990937189643190302
          來源:掘金
          著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。



          瀏覽 55
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  老色批影院| 微拍福利手机在线 | 无码在线精品视频 | 国产又爽 又黄 免费网站在线观看 | 国产激情视频免费在线看 |