天天看點

阿裡進階技術專家談開源DDD架構:COLA4.0,分離架構群組件

cola: clean object-oriented & layered architecture    https://github.com/alibaba/cola/

前幾天和幾個餓了麼的同學聊天,一聽說他們還在用cola 1.0,我二話沒說,90度鞠躬,賠禮道歉,虛心聆聽他們的吐槽。cola的初衷旨在控制複雜度,救碼農于水火,慚愧的是,早期的思想不成熟,設計也多有缺陷,不僅沒幫到他們,反而坑了他們,實在抱歉。

實際上,我在cola 3.0疊代的時候,已經舉起奧卡姆剃刀,砍掉了很多東西。

然而還不夠,主要展現在對架構的思考還不夠透徹。再三考量,我覺得有必要對cola進行一次重新梳理,回歸初心,讓cola真正成為應用架構的最佳實踐,幫助廣大的業務技術同學,脫離醬缸代碼的泥潭!

應用架構的本質

什麼是架構?十個人可能有十個回答,架構在技術的語境下,就和架構師一樣魔幻。我曾經看過一本技術書,用了一章的篇幅讨論架構的定義,最終也沒有說明白。

實際上,定義架構也沒那麼難,如下圖所示,架構的本質,簡單來說,就是要素結構。所謂的要素(components)是指架構中的主要元素,結構是指要素之間的互相關系(relationship)。

阿裡進階技術專家談開源DDD架構:COLA4.0,分離架構群組件

例如組織架構,其要素是什麼?組成組織的要素當然是人,結構呢?結構是人與人之間的關系。是以,組織架構就是關于定義人的職責劃分,以及人與人之間協作關系的一種設計方法。

同樣,對于應用架構而言,代碼是其核心組成要素,結構就是這些代碼該如何被組織,也就是要如何處理子產品(module)、元件(component)、包(package)和類(class)之間的關系。簡而言之,應用架構就是要解決代碼要如何被組織的問題。

阿裡進階技術專家談開源DDD架構:COLA4.0,分離架構群組件

一個沒有架構的應用系統,就像一堆随意堆放、雜亂無章的玩具,隻有熵值,沒有熵減。而一個有良好架構的應用系統,有章法、有結構,一切都顯得井井有條。

好的組織架構會遵循一定的架構模式,大部分的組織都會按職能和業務來設計自己的架構。如果你反其道而行之,硬要把銷售、财務和技術人員放在一個部門,就會顯得很奇怪。

阿裡進階技術專家談開源DDD架構:COLA4.0,分離架構群組件

同樣,好的應用架構,也遵循一些共同模式,不管是六邊形架構、洋蔥圈架構、整潔架構、還是cola架構,都提倡以業務為核心,解耦外部依賴,分離業務複雜度和技術複雜度。

應用架構的本質,就是要從繁雜的業務系統中提煉出共性,找到解決業務問題的最佳共同模式,為開發人員提供統一的認知,治理混亂。幫助應用系統“從混亂到有序”,cola架構就是為此而生,其核心職責就是定義良好的應用結構,提供最佳實踐。

cola 架構

自從cola誕生以來,已經被使用在很多的業務系統裡面,有crm的業務,有電商的業務,有物流的業務,有外賣業務,有排課系統…. cola作為應用架構,有一定的普适性,是因為業務問題都有一定的共性。例如,典型的業務系統都需要:

•          接收request,響應response;

•          做業務邏輯處理,像校驗參數,狀态流轉,業務計算等等;

•          和外部系統有關聯,像資料庫,微服務,搜尋引擎等;

正是有這樣的共性存在,才會有很多普适的架構思想出現,比如分層架構、六邊形架構、洋蔥圈架構、整潔架構(clean architecture)、ddd架構等等。

這些應用架構思想雖然很好,但我們很多同學還是“不講co德,明白了很多道理,可還是過不好這一生”。問題就在于缺乏實踐和指導。cola的意義就在于,他不僅是思想,還提供了可落地的實踐。應該是為數不多的應用架構層面的開源軟體。

假如你是一個公司的cto要管100号人,你怎麼管?按照管理學的定義,一個人的管理幅度如果超過10個,管理就會變得很困難。是以,管100号人,你可以把他們分成10個小組,這樣你管理10個小組長就好了。

所有的複雜系統都會呈現出層級結構,管理如此,軟體設計也不例外,你能想象如果網絡協定不是四層,而是一層,意味着,你要在應用層去處理鍊路層的bit資料流會是怎樣的情景嗎?同樣,應用系統處理複雜業務邏輯也應該是分層的,下層對上層屏蔽處理細節,每一層各司其職,分離關注點,而不是一個serviceimpl解決所有問題。

對于一個典型的業務應用系統來說,cola會做如下層次定義,每一層都有明确的職責定義:

阿裡進階技術專家談開源DDD架構:COLA4.0,分離架構群組件

1)适配層(adapter layer):負責對前端展示(web,wireless,wap)的路由和适配,對于傳統b/s系統而言,adapter就相當于mvc中的controller;

2)應用層(application layer):主要負責擷取輸入,組裝上下文,參數校驗,調用領域層做業務處理,如果需要的話,發送消息通知等。層次是開放的,應用層也可以繞過領域層,直接通路基礎實施層;

3)領域層(domain layer):主要是封裝了核心業務邏輯,并通過領域服務(domain service)和領域對象(domain entity)的方法對app層提供業務實體和業務邏輯計算。領域是應用的核心,不依賴任何其他層次;

4)基礎實施層(infrastructure layer):主要負責技術細節問題的處理,比如資料庫的crud、搜尋引擎、檔案系統、分布式服務的rpc等。此外,領域防腐的重任也落在這裡,外部依賴需要通過gateway的轉義處理,才能被上面的app層和domain層使用。

分層是屬于大粒度的職責劃分,太粗,我們有必要往下再down一層,細化到包結構的粒度,才能更好的指導我們的工作。

還是拿一堆玩具舉例子,分層類似于拿來了一個架子,分包類似于在每一層架子上又放置了多個收納盒。所謂的内聚,就是把功能類似的玩具放在一個盒子裡,這樣可以讓應用結構清晰,極大的降低系統的認知成本和維護成本。

阿裡進階技術專家談開源DDD架構:COLA4.0,分離架構群組件

那麼,對于一個後端應用來說,應該需要哪些收納盒呢?這一塊的設計真可謂是費了老鼻子勁了,基本上每一次cola的疊代都會涉及到包結構的調整,疊代到現在,才算基本穩定下來。

阿裡進階技術專家談開源DDD架構:COLA4.0,分離架構群組件

各個包結構的簡要功能描述,如下表所示:

層次

包名

功能

必選

adapter層

web

處理頁面請求的controller

wireless

處理無線端的适配

wap

處理wap端的适配

app層

executor

處理request,包括command和query

consumer

處理外部message

scheduler

處理定時任務

domain層

model

領域模型

ability

領域能力,包括domainservice

gateway

領域網關,解耦利器

infra層

gatewayimpl

網關實作

mapper

ibatis資料庫映射

config

配置資訊

client sdk

api

服務對外透出的api

dto

服務對外的dto

你可能會有疑問,為什麼domain的model是可選的?因為cola是應用架構,不是ddd架構。在工作中,很多同學問我領域模型要怎麼設計,我的回答通常是:無有必要勿增實體。領域模型對設計能力要求很高,沒把握用好,一個錯誤的抽象還不如不抽象,甯可不要用,也不要濫用,不要為了ddd而ddd。

問題的關鍵是要看,新增的模型沒有給你帶來收益。比如有沒有幫助系統解耦,有沒有提升業務語義表達能力的提升,有沒有提升系統的可維護性和可測性等等。

模型雖然可選,但ddd的思想是一定要去學習和貫徹的,特别是統一語言、邊界上下文、防腐層的思想,值得深入學習,仔細體會。實際上,cola裡面的很多設計思想都來自于ddd。其中就包括領域包的設計。

前面的包定義,都是功能次元的定義。為了兼顧領域次元的内聚性,我們有必要對包結構進行一下微調,即頂層包結構應該是按照領域劃分,讓領域内聚。

也就是說,我們要綜合考慮功能和領域兩個次元包結構定義。按照領域和功能兩個次元分包政策,最後呈現出來的,是如下圖所示的頂層包節點是領域名稱,領域之下,再按功能劃分包結構。

阿裡進階技術專家談開源DDD架構:COLA4.0,分離架構群組件

例如,在我們剛剛上線的一個雲店鋪(cloudstore)項目中,按照cola的分包政策,我們在每一個module下面首先按照領域做一個頂層劃分,然後在領域内,再按照功能進行分包。

阿裡進階技術專家談開源DDD架構:COLA4.0,分離架構群組件

“高内聚,低耦合”這句話,你工作的越久,就越會覺得其有道理。

所謂耦合就是聯系的緊密程度,隻要有依賴就會有耦合,不管是程序内的依賴,還是跨程序的rpc依賴,都會産生耦合。依賴不可消除,同樣,耦合也不可避免。我們所能做的不是消除耦合,而是把耦合降低到可以接受的程度。在軟體設計中,有大量的設計模式,設計原則都是為了解耦這一目的。

在ddd中有一個很棒的解耦設計思想——防腐層(anti-corruption),簡單說,就是應用不要直接依賴外域的資訊,要把外域的資訊轉換成自己領域上下文(context)的實體再去使用,進而實作本域和外部依賴的解耦。

在cola中,我們把ac這個概念進行了泛化,将資料庫、搜尋引擎等資料存儲都列為外部依賴的範疇。利用依賴倒置,統一使用gateway來實作業務領域和外部依賴的解耦。

其實作方式如下圖所示,主要是在domain層定義gateway接口,然後在infrastructure提供gateway接口的實作。

阿裡進階技術專家談開源DDD架構:COLA4.0,分離架構群組件

舉個例子,假如有一個電商系統,對于下單這個操作,它需要關聯訂單服務、商品服務、庫存服務、營銷服務等多個系統才能完成。

那麼在訂單域,該如何擷取商品和庫存資訊呢?最直接的方式,無外乎就是rpc調用商品和庫存服務,拿到dto直接使用就完了。

然而,商品域吐出的是一個大而全的dto(可能包含幾十個字段),而在下單這個階段,訂單所需要的可能隻是其中幾個字段而已。更合适的做法,應該是在訂單域中,使用gateway對商品域和庫存域的依賴進行解耦。

阿裡進階技術專家談開源DDD架構:COLA4.0,分離架構群組件

這樣做有兩個好處,一個是降低了對外域資訊依賴的耦合;另一個是通過上下文映射(context mapping),確定本領域邊界上下文(bounded context)下領域知識的完整性,實作了統一語言(ubiquitous language)。

以上就是cola架構的核心内容了。然而這麼多module,這麼多package,如果要手動去建立的話,是非常繁瑣和費時的。為了能夠快速建立滿足cola架構的應用,我建立了兩個maven archetype。

1.        一個是用來建立純後端服務的archetype:cola-archetype-service。

2.        一個是用來建立adapter和後端服務一體的web應用archetype:cola-archetype-web。

另外,你也可以使用阿裡雲的應用生成器去生成一個cola應用,隻是那邊的版本沒有同步更新,可能會老舊一點。

cola元件

使用過老版本cola的同學,應該知道,cola除了架構之外,還提供了一些架構級别的功能,比如攔截器功能,擴充點功能等。

之前,這種架構功能和架構混淆在一起,會讓人以為使用cola,就必須要使用這些功能。實際上二者是可以分開使用的,也就是說,你可以單純的使用cola架構,而不使用任何cola元件提供的功能也是完全沒問題的。

當然,我還是強烈推薦你可以有選擇的使用這些cola元件,畢竟這些元件都是我們在實際工作中的總結沉澱,其複用性和價值是被反複驗證過的。

為了友善管理,以及更清晰的把架構和架構區分開來。在此次cola 4.0的更新中,我把這些功能元件全部收攏到了cola-components下面。到目前為止,我們已經沉澱了以下元件:

元件名稱

版本

依賴

cola-component-dto

定義了dto格式,包括分頁

1.0.0

cola-component-exception

定義了異常格式,主要有bizexception和sysexception

cola-component-statemachine

狀态機元件

cola-component-domain-starter

spring托管的領域實體元件

cola-component-catchlog-starter

異常處理和日志元件

exception,dto元件

cola-component-extension-starter

擴充點元件

cola-component-test-container

測試容器元件

這些元件是一個良好的開端,我相信,在未來會有更多有用的元件加入。當然,作為一個開源項目,如果你有好的元件idea,歡迎你随時為這個元件庫添磚加瓦。

cola 4.0

總結一下,在本次cola更新中,我們進一步明确了架構和架構功能的定義。更新之後,如下圖所示,cola會被分成cola架構和cola元件兩個部分:

1.        cola架構:關注應用架構的定義和建構,提升應用品質。

2.        cola元件:提供應用開發所需要的可複用元件,提升研發效率。

阿裡進階技術專家談開源DDD架構:COLA4.0,分離架構群組件

cola 開源位址: https://github.com/alibaba/cola

你可以按照以下步驟去使用cola:

** 第一步:安裝 cola archetype ** 下載下傳cola-archetypes下的源碼到本地,然後本地運作mvn install安裝。

** 第二步:安裝 cola components ** 下載下傳cola-components下的源碼到本地,然後本地運作mvn install安裝。

** 第三步:建立應用 ** 執行以下指令:

mvn archetype:generate  -dgroupid=com.alibaba.demo -dartifactid=demoweb -dversion=1.0.0-snapshot -dpackage=com.alibaba.demo -darchetypeartifactid=cola-framework-archetype-web -darchetypegroupid=com.alibaba.cola -darchetypeversion=4.0.0

指令執行成功的話,會看到如下的應用代碼結構:

阿裡進階技術專家談開源DDD架構:COLA4.0,分離架構群組件

** 第四步:運作應用 ** 首先在demoweb目錄下運作mvn install(如果不想運作測試,可以加上-dskiptests參數)。然後進入start目錄,執行mvn spring-boot:run。運作成功的話,可以看到springboot啟動成功的界面。

生成的應用中,已經實作了一個簡單的rest請求,可以在浏覽器中輸入 http://localhost:8080/helloworld 進行測試。

作者簡介:

阿裡巴巴進階技術專家,張建飛。著有《代碼精進之路:從碼農到工匠》,憑借此書,獲得2020年人民郵電出版社it類最佳作者。是開源應用架構cola的作者,擅長應用架構和領域模組化。更多技術精華内容,請關注作者的微信公衆号:從碼農到工匠。