一、整潔架構(gòu)分層
整潔架構(gòu)分層如圖所示,從內(nèi)到外分別為實體->用例->接口適配器->框架與驅(qū)動程序。其中實體層和用例層包含業(yè)務(wù)邏輯、接口適配器層是翻譯層,負責(zé)把外部數(shù)據(jù)翻譯成業(yè)務(wù)層能夠識別的結(jié)構(gòu)、框架與驅(qū)動程序負責(zé)各種IO。

二、DDD分層
六邊形分層
1、我們最初落地的DDD分層架構(gòu)如下圖所示,這種分層結(jié)構(gòu)類似于六邊形架構(gòu),本質(zhì)上把代碼分成了2層,一層是業(yè)務(wù)邏輯和業(yè)務(wù)邏輯依賴的接口、另一層是接口的具體實現(xiàn)和數(shù)據(jù)庫、框架等細節(jié)。
2、在這種DDD分層架構(gòu)中,內(nèi)層圓代表業(yè)務(wù)邏輯層,其中實體、值對象、聚合、領(lǐng)域服務(wù)等都對應(yīng)于整潔架構(gòu)中的實體層;應(yīng)用服務(wù)層對應(yīng)的是整潔架構(gòu)中的用例層。
3、這種分層結(jié)構(gòu)的缺點是不完全符合整潔架構(gòu)要求的插件式架構(gòu),雖然我們可以把appliation層和domain層整體打包,適配不同數(shù)據(jù)庫、前端、框架等。application層和domain層中的domain service不包含業(yè)務(wù)邏輯,只包含接口,這些業(yè)務(wù)邏輯還需要再實現(xiàn)遍。

整潔分層
1、由于我們項目是toB項目,不同甲方公司對數(shù)據(jù)庫、前端、框架等這些技術(shù)要求可能不一致,比如有的公司要求使用mysql、有的公司要求使用oracle。但是業(yè)務(wù)邏輯是基本一致的,這非常符合插件式架構(gòu),于是我們對架構(gòu)做了改進。
2、等等,看起來和上面的一樣?嗯,整體上圖差不多,區(qū)別在細節(jié)上,application和domain層里的應(yīng)用服務(wù)和領(lǐng)域服務(wù)包含了具體實現(xiàn),只有服務(wù)具體實現(xiàn)有其他依賴的時候才引入這個依賴的接口,而不是整體把應(yīng)用服務(wù)和領(lǐng)域服務(wù)的實現(xiàn)類放到infrastructure里面。
3、整潔架構(gòu)里有一個老大難問題,就是事務(wù)的處理。我們一般會在application層中處理事務(wù),原來六邊形架構(gòu)的時候application層的實現(xiàn)是在infrastructure里,是可以依賴spring的,方法上直接加個@Transactional注解就行;但是整潔架構(gòu)中要求application層即要有業(yè)務(wù)邏輯實現(xiàn),又不能依賴spring等框架,所以事務(wù)的處理和依賴關(guān)系管理變得困難。
- 解決方案:關(guān)于依賴關(guān)系注入我們可以在infrastructure或者starter啟動模塊里通過@configuration進行注入。關(guān)于事務(wù)管理我們可以借用spring手動提交事務(wù),然后借助注解和切面實現(xiàn)新的事務(wù)注解,這樣application就即包含業(yè)務(wù)邏輯又可以處理依賴關(guān)系和事務(wù)了。
4、此時我們可以說實現(xiàn)了比較全面的插件式架構(gòu),我們可以單獨交付domain層,然后去實現(xiàn)一個符合該公司業(yè)務(wù)場景的application層及技術(shù)細節(jié)層。有的公司業(yè)務(wù)場景有可能和我們實現(xiàn)的重復(fù),那么我們又可以把domain層和application層一起交付,只需要按照該公司技術(shù)要求來實現(xiàn)技術(shù)細節(jié)。對于沒有技術(shù)要求,且場景也重復(fù)的公司,我們可以直接交付完整項目。

三、實現(xiàn)細節(jié)
1、數(shù)據(jù)庫是實現(xiàn)細節(jié)
- DDD設(shè)計中我們是從domain出發(fā),推后設(shè)計表結(jié)構(gòu)
- 假如內(nèi)存無限大、永不宕機,那么我們只設(shè)計對象數(shù)據(jù)結(jié)構(gòu),不用考慮數(shù)據(jù)庫,所以數(shù)據(jù)庫是關(guān)乎磁盤的IO
2、web是實現(xiàn)細節(jié)
- DDD設(shè)計中不會首先考慮UI等的數(shù)據(jù)結(jié)構(gòu),推后通過cqrs直接查表翻譯成DTO、或者領(lǐng)域?qū)ο蠓g成DTO,所以UI數(shù)據(jù)結(jié)構(gòu)設(shè)計可能比表設(shè)計還要靠后
- Web本質(zhì)上是一種網(wǎng)絡(luò)IO
3、應(yīng)用框架是實現(xiàn)細節(jié)
- 框架如spring主要用來管理依賴關(guān)系,管理事務(wù)等,當(dāng)我們引入框架后,如果沒有做特殊管理,后來人可以很隨便的把各種工具類、template類等引入到業(yè)務(wù)代碼中,導(dǎo)致依賴關(guān)系混亂
- 框架升級可能導(dǎo)致我們依賴不需要依賴的東西,違背單一職責(zé)
- 未來可能切換到更好的框架,而切換一定會影響業(yè)務(wù)邏輯
4、各種redis、kafka、es等中間件也是技術(shù)細節(jié)
- 這些本質(zhì)上都是網(wǎng)絡(luò)IO
- 版本升級等都會影響業(yè)務(wù)邏輯