成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

你的分層架構(gòu)還好嗎?

開(kāi)發(fā) 架構(gòu)
當(dāng)我們開(kāi)始一個(gè)新的項(xiàng)目,我們就開(kāi)始創(chuàng)建一個(gè)個(gè)折文件夾。哦,不對(duì),那我們?cè)谧龇謱蛹軜?gòu)設(shè)計(jì)。架構(gòu)最后落到現(xiàn)有的計(jì)算機(jī)操作系統(tǒng)上,其的展示形式是分層架構(gòu)。畢竟,硅基不如碳基。

 分層架構(gòu),不就是建文件夾的藝術(shù)嗎?

[[285132]]

注:本文更適用于中大型項(xiàng)目,小項(xiàng)目開(kāi)心就好了。因?yàn)闀r(shí)代的原因,對(duì)部分詞匯描述可能不是那么準(zhǔn)確,歡迎指正。

當(dāng)我們開(kāi)始一個(gè)新的項(xiàng)目,我們就開(kāi)始創(chuàng)建一個(gè)個(gè)折文件夾。哦,不對(duì),那我們?cè)谧龇謱蛹軜?gòu)設(shè)計(jì)。架構(gòu)最后落到現(xiàn)有的計(jì)算機(jī)操作系統(tǒng)上,其的展示形式是分層架構(gòu)。畢竟,硅基不如碳基。

可是呢,為什么我們要做分層架構(gòu)設(shè)計(jì)呢?通過(guò)層(Layer)來(lái)隔離不同的關(guān)注點(diǎn)。

So,我要開(kāi)始瞎扯了。

基本思想:關(guān)注點(diǎn)分離,劃分邊界

注:三層架構(gòu)(controller-service-model)并非等于于 MVC 架構(gòu)模式。對(duì)于其的錯(cuò)誤等同,導(dǎo)致了架構(gòu)上的一系列錯(cuò)誤。

 

問(wèn)題:落后的三層架構(gòu)

過(guò)去,我總以為對(duì)于大部分項(xiàng)目來(lái)說(shuō),三層分層架構(gòu)之外的部分是大泥球,即隨意化的代碼組織方式。然而,我發(fā)現(xiàn)對(duì)于大部分的項(xiàng)目來(lái)說(shuō),三層分層架構(gòu)的 service 也是個(gè)大泥球,我忘記了三層分層架構(gòu)的 model 層也是一堆大泥球。Controller 相對(duì)好一點(diǎn),但是對(duì)于某些項(xiàng)目來(lái)說(shuō)也是個(gè)小泥球。

大泥球是指一個(gè)隨意化的雜亂的結(jié)構(gòu)化系統(tǒng),只是代碼的堆砌和拼湊,往往會(huì)導(dǎo)致很多錯(cuò)誤或者缺陷。

在今天 DDD + 整潔架構(gòu)流行的今天, 三層分層架構(gòu)已經(jīng)完全不能滿足現(xiàn)有應(yīng)用的需求,甚至看上去一團(tuán)糟糕。它存在這么一些問(wèn)題:

  1. 統(tǒng)一管理是魔鬼,如 controller 文件夾下一堆的代碼,到處亂放的 model。
  2. 缺乏明確的職責(zé)劃分,如 controller 承擔(dān)了 service 的職責(zé)
  3. 臃腫的 service,和貧血的 model
  4. 三層分層之后的隨意文件組織方式,如 kafka 等到處亂放的代碼
  5. ……

可是,為什么會(huì)這樣呢?

  1. 職責(zé)(or 限界上下文)沒(méi)有劃分明確和清晰
  2. model 層存在大量的二義性
  3. 技術(shù)導(dǎo)向架構(gòu)模式
  4. ……

于是,我們有了一些基本的解決方案,或者說(shuō)是套路。

重新定義:消除二義性

 

當(dāng)我們談?wù)?service 的時(shí)候,我們談?wù)摰氖峭粋€(gè) service 嗎?

當(dāng)我們談?wù)?model 的時(shí)候,我們談?wù)摰氖峭环N model 嗎?

若對(duì)于一個(gè)文法的某一句子存在兩棵不同的語(yǔ)法樹(shù),則該文法是二義性文法。

如果有多種不同類型的類,都被放置在 model 包下。那么,你應(yīng)該消除 model 這個(gè)包,改為更表意的名稱,如 Entity、* Request、* Response 等等。同理,一旦你們展開(kāi)對(duì)某個(gè)名稱的討論時(shí),是時(shí)候好好考慮其中的二義性。

最后,你還需要有一個(gè)相關(guān)領(lǐng)域的名詞表。

劃分邊界:業(yè)務(wù)導(dǎo)向架構(gòu)

開(kāi)始之前不得不說(shuō)的是:

  • 微服務(wù)是一種業(yè)務(wù)導(dǎo)向架構(gòu)。
  • 微服務(wù)是一種業(yè)務(wù)導(dǎo)向架構(gòu)。
  • 微服務(wù)是一種業(yè)務(wù)導(dǎo)向架構(gòu)。

所以,如果你的微服務(wù)劃分出現(xiàn)了不同的幾個(gè)技術(shù)維度的服務(wù),那么你需要好好反思一下。

So,為了迎接業(yè)務(wù)導(dǎo)向架構(gòu),我們需要以采用水平 + 垂直架構(gòu)的方式來(lái)重新劃分架構(gòu),將各業(yè)務(wù)模板的代碼聚合到各自的業(yè)務(wù)模板中,順便把大量地 util 和 common 內(nèi)聚到服務(wù)中。而它們都基于其它低層模板。

隨后,我們還可以嘗試將單體應(yīng)用拆分到微服務(wù)。

但是,我們都不應(yīng)該依賴于低層模塊,于是就有了……。

關(guān)注點(diǎn)分離:針對(duì)接口編程

我們看到了整潔架構(gòu):

 

在其中有一個(gè)非常重要的原則:

依賴倒置原則:高層模塊不應(yīng)該依賴于低層模塊,二者都應(yīng)該依賴于抽象。

這一點(diǎn)在大部分的項(xiàng)目中,已經(jīng)實(shí)踐得相關(guān)的好。畢竟,有各種各樣的 * Service + * ServiceImpl。

除此,為了實(shí)現(xiàn)這樣的目標(biāo),對(duì)于采用 DDD 架構(gòu)的應(yīng)用來(lái)說(shuō),在我們的 domain 層的限界上下文,除了包含自身的 entity、vo 等,它應(yīng)該還帶有 repository 的抽象。這樣一來(lái),我們的 domain 層便不依賴

應(yīng)用分層:DDD 與整潔架構(gòu)

 

所以,讓我們來(lái)看個(gè)問(wèn)題。這是一個(gè)在 GitHub 上 star 數(shù)接近 15K 的 Java 語(yǔ)言編寫(xiě)的開(kāi)源 CMS 中,某個(gè)模塊的代碼目錄:

  1. ├── cms-admin/ 
  2. ├── cms-common/ 
  3. ├── cms-dao/ 
  4. ├── cms-job/ 
  5. ├── cms-rpc-api/ 
  6. ├── cms-rpc-service/ 
  7. ├── cms-search/ 
  8. └── cms-web/ 

這是一個(gè)技術(shù)導(dǎo)向的應(yīng)用架構(gòu)。所以,當(dāng)我要新加一個(gè)功能的時(shí)候,我需要:

  1. 在 cms-dao 模塊中加一個(gè) model 和一個(gè) mapper
  2. 在 cms-rpc-service 模塊中加一個(gè) service
  3. 在 cms-web 模塊中中加一個(gè) controller

“完美”,沒(méi)有什么問(wèn)題啊。

而隨著時(shí)間的推移,你現(xiàn)在已經(jīng)有一個(gè)巨大無(wú)比的 model 層,修改代碼時(shí)需要在不同的模塊跳轉(zhuǎn)。而不能快速修改相關(guān)的代碼。甚至于,你無(wú)法采用微服務(wù)架構(gòu),你是一個(gè)巨大的單體應(yīng)用。

為了挽救這樣的一個(gè)項(xiàng)目,我們不得不嘗試做一些事情。

切割基礎(chǔ)設(shè)施

 

你的基礎(chǔ)設(shè)施自開(kāi)發(fā)完成之后,基本不變,而你的業(yè)務(wù)代碼一直在發(fā)生變化。

引起技術(shù)實(shí)現(xiàn)發(fā)生變化的原因與引起領(lǐng)域邏輯發(fā)生變化的原因顯然不同,這就導(dǎo)致基礎(chǔ)設(shè)施和領(lǐng)域邏輯問(wèn)題會(huì)以不同速率發(fā)生變化。——《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)模式、原理與實(shí)踐》

當(dāng)你來(lái)到一個(gè)項(xiàng)目一眼看到這么多基礎(chǔ)設(shè)施相關(guān)的目錄結(jié)構(gòu)時(shí):

  1. ├── controller 
  2. ├── interceptor 
  3. ├── jms 
  4. ├── rocketmq 
  5. ├── schedule 
  6. └── task 

有一天,我們又加了一個(gè) Kafka,我們又不新加一個(gè)文件夾,而這樣的分層設(shè)計(jì)看上去沒(méi)有一點(diǎn)組織。然后呢,我們打開(kāi)目錄的時(shí)候,無(wú)法快速定位到我們的代碼。

除了從目錄上 infrastructure 包/層,容納相關(guān)的基礎(chǔ)設(shè)施代碼。我們還要考慮到分層上的單一職責(zé),因?yàn)樾枰獎(jiǎng)冸x基礎(chǔ)設(shè)施與業(yè)務(wù)代碼的關(guān)系。所以,為了實(shí)現(xiàn) Clean Architecture 的大業(yè),你還需要一層抽象接口,比如你要訪問(wèn)存儲(chǔ)業(yè)務(wù)相關(guān)的數(shù)據(jù)。那么抽象在你的 domain 中,具體的 RepositoryImpl 實(shí)現(xiàn)是在你的基礎(chǔ)設(shè)施。

離心分離模型

 

在一個(gè)系統(tǒng)中,你會(huì)存在這么一些不同的 model:

(PS:部分描述可能不準(zhǔn)確,歡迎指正)

  • 與數(shù)據(jù)庫(kù)表結(jié)構(gòu)對(duì)應(yīng)的 DO( Data Object)/ PO(Persistant Object)。
  • 查詢數(shù)據(jù)的 Query、Request。
  • 對(duì)外傳輸?shù)膶?duì)象:DTO( Data Transfer Object)。
  • 業(yè)務(wù)層之間的數(shù)據(jù)對(duì)象:VO(Value Object) / BO(Business Object)。
  • 訪問(wèn)數(shù)據(jù)庫(kù)的:DAO (Data Access Object數(shù)據(jù)訪問(wèn)對(duì)象)。
  • 以及我們想要的 DDD 中的實(shí)體 Entity
  • 還有其它的 POJO( Plain Ordinary Java Object)

但是它們都是 model,所以它們都被扔到 model 中……,又或者是 bean 中……。導(dǎo)致,你有了一個(gè)巨大比的 model 層。

所以,在 DDD 又或者是 Clean Architecture,我們重新命名了不同的模式:

  • 使用 Command / Request 作為輸入?yún)?shù)。其中的 Command 模式在完成后需要發(fā)出對(duì)應(yīng)的 Event。
  • 使用 Response / DTO / Representation 作為返回結(jié)果。
  • 對(duì) Entity 大家保持了一致的意見(jiàn)
  • 還有 PO / DO 作為作為數(shù)據(jù)庫(kù)的存儲(chǔ)模型
  • DAO 作為數(shù)據(jù)庫(kù)的訪問(wèn)模型
  • ……

不過(guò),其實(shí)你只要不再讓使用 model 和 bean,相似會(huì)有更多地收獲。

以領(lǐng)域?yàn)楹诵模S富行為

 

當(dāng)完成了大坨的移動(dòng)文件夾操作之后,我們來(lái)到了最麻煩和復(fù)雜的一部分。

我們需要對(duì)領(lǐng)域模型進(jìn)行重新建模,重新規(guī)劃 model 和 service,讓 model 變成了富血模型。也許,你需要一場(chǎng) Event Storming,才能完成真正意義的事件風(fēng)暴建模。不過(guò),步驟上也不會(huì)有太多的差異。

  1. 重新劃分包。即在保持業(yè)務(wù)不中斷的情況下重構(gòu),以讓新的代碼運(yùn)行在新的架構(gòu)上。
  2. 分析抽象領(lǐng)域模型
  3. 編寫(xiě) API 測(cè)試,保證現(xiàn)有的功能
  4. 編寫(xiě)抽象接口,進(jìn)行依賴反轉(zhuǎn)
  5. 拆分 service 層,重構(gòu)代碼。將行為綁定于是領(lǐng)域?qū)ο笊稀?/li>

其它的情況,還要進(jìn)行 case by case 的分析。

剩下的呢?

共享的業(yè)務(wù)邏輯,可以采用 sharedkernel,或者其它模式來(lái)處理。

待繼續(xù)補(bǔ)充。

代碼共用分層:功能內(nèi)聚

 

創(chuàng)建通用的共享組件導(dǎo)致了一系列問(wèn)題,比如耦合、協(xié)調(diào)難度和復(fù)雜度增加。

當(dāng)我看到一個(gè)個(gè)巨大的 common 包時(shí),我開(kāi)始痛恨 common、 base、 util 這些該死的包,還有它們目錄下統(tǒng)一管理的 bean。我們真的已經(jīng)把它們用爛了,所以你應(yīng)該重新審視一下你的項(xiàng)目代碼。

所以,從這種意義上來(lái)說(shuō):復(fù)用與低耦合,本身存在一定的互斥關(guān)系。

base 下的 base

過(guò)去,我曾經(jīng)重構(gòu)過(guò)一個(gè) base 項(xiàng)目的代碼,正是這次重構(gòu)讓我意識(shí)到 base 并不是一個(gè)好東西。如果在項(xiàng)目中已經(jīng)抽取出了一個(gè) base 模塊,那么這個(gè)模塊下是不應(yīng)該存在 base 這樣的業(yè)務(wù)邏輯。而且,base 這個(gè)東西導(dǎo)致了一個(gè)問(wèn)題是,只要是共用的東西就會(huì)不加思索的扔到 base 中。

你會(huì)有一個(gè) base 的包,放著各種抽象接口,但是你需要一個(gè)更好的名字,比如 concepts,比如 support。

總之,你不應(yīng)該存在 base 模塊,讓開(kāi)發(fā)人員思考一下哪去放新的類。

無(wú)比臃腫的 bean 和 model

“這本身是怪不得程序員的,要怪就怪該死的 Java 語(yǔ)言。”

轉(zhuǎn)而,我開(kāi)始考慮一個(gè)問(wèn)題,當(dāng)個(gè)包(文件夾)下的文件數(shù)是否不應(yīng)該超過(guò)一定的數(shù)量?

如果一個(gè)包下的類數(shù),超過(guò)一定的范圍,那么我們應(yīng)該考慮是否存在職責(zé)相似的類。

這部分可以參考上一部分的離心分離模型。

什么不是 common

common 這個(gè)名字真的很爛,比 base 和 model 更爛。

一旦你從項(xiàng)目中拆出了一個(gè) common 模塊,那只會(huì)有一個(gè)結(jié)果,你將得到一個(gè) 5G 時(shí)代的 jar 包。甚至于,你看到有一塊代碼在 IDE 中是灰色的、未使用的,你也不敢輕易去刪除這些代碼。直到有一天,這個(gè) common 包構(gòu)建出來(lái)的大小有 10M、20M,而你只需要引用一個(gè) AESUtil 的時(shí)候,你才發(fā)現(xiàn)了問(wèn)題:原本幾十 K 的 hello, world,現(xiàn)在變成了幾十 M。

不要事先創(chuàng)建 common 模塊,你可能不會(huì)有這個(gè)模塊。

任何的水平分層拆分應(yīng)用,在項(xiàng)目復(fù)雜化的今天都是不靠譜的。

誰(shuí)用誰(shuí)管理,而不是覺(jué)得是 common 就扔 common 模塊。

它真是個(gè) util 嗎?

 

哦,不,它是個(gè)惡魔,因?yàn)樗?util。

你會(huì)往 xxUtil 不加思索地扔入邏輯,正如你會(huì)往 common/bean 中扔入所有的 model,直次有一天,你擁有一個(gè)巨大無(wú)比的 base、common 代碼。

大多數(shù)情況下,所有和業(yè)務(wù)相關(guān)的 Util 都存在一定的問(wèn)題,如 CaptchaUtil,它要么應(yīng)該劃到自己的上下文中去,要么扔到諸如于 domain/shared 等共享上下文,而不是和其它 util 放到一起。

而諸如 FileUtil、DateUtil、RedisUtil、JdbcUtil 這些都可以說(shuō)是基礎(chǔ)設(shè)施相關(guān)的部分,它們可以劃到 infrastructure/file 又或者是 infrastructure/date 目錄下,而不是統(tǒng)一的管理這些 util。

如 StackOverflow 的相關(guān)問(wèn)題所列,我們還有諸如 Coordinator、Builder、Writer、Reader、Handler、Container、Protocol、Target、Converter、Controller、View、Factory、Entity、Bucket 等名稱。

試著干掉 Util,你將收獲更多的類,笑~。

需要個(gè)例子?

看看 Spring Framework 的源碼的分層結(jié)構(gòu),如 Spring Orm:

  1. └── orm 
  2.  ├── ObjectOptimisticLockingFailureException.java 
  3.  ├── ObjectRetrievalFailureException.java 
  4.  ├── hibernate5a/ 
  5.  ├── jpa/ 
  6.  └── package-info.java 

又或者是 spring-context 下的目錄分層結(jié)構(gòu):

  1. └── springframework 
  2.  ├── cache 
  3.  │   ├── annotation 
  4.  │   ├── concurrent 
  5.  │   ├── config 
  6.  │   ├── interceptor 
  7.  │   └── support 
  8.  ├── context 
  9.  │   ├── annotation 
  10.  │   ├── config 
  11.  │   ├── event 
  12.  │   ├── expression 
  13.  │   ├── i18n 
  14.  │   ├── index 
  15.  │   ├── support 
  16.  │   └── weaving 

它們都在自己的限界上下文內(nèi),維護(hù)自己的 annotaion、bean、support、i18n 等等的包。

分層架構(gòu)重構(gòu)

 

所以,我們可以嘗試這么去做架構(gòu)重構(gòu)

  1. 分析、診斷現(xiàn)有項(xiàng)目結(jié)構(gòu)
  2. 劃分新的分層架構(gòu)
  3. 功能測(cè)試
  4. 使用抽象解耦依賴
  5. 進(jìn)行細(xì)粒度的代碼重構(gòu)
  6. 重新劃分領(lǐng)域服務(wù)

還有嗎?

  1. 不要預(yù)先設(shè)計(jì),而是定義原則與規(guī)范。
  2. 以簡(jiǎn)單的設(shè)計(jì)開(kāi)始,在生命周期中演進(jìn)架構(gòu)。
  3. 以多個(gè) common 包,替代統(tǒng)一的 common 包
  4. TBC。

結(jié)論

 

那么,我們?cè)趺床拍茏龊梅謱蛹軜?gòu)呢?

by experience。

哦,不對(duì),DDD 大法好。

責(zé)任編輯:武曉燕 來(lái)源: Phodal phodal
相關(guān)推薦

2012-05-11 09:45:07

海量數(shù)據(jù)

2022-02-22 19:26:58

Wi-Fi 6EWi-Fi 7Wi-Fi 6

2009-07-27 10:11:08

富士康孫丹勇

2019-05-23 11:23:50

2013-07-15 09:57:24

微軟SaaSTurner

2023-03-09 08:13:34

2022-05-17 14:17:50

物理安全網(wǎng)絡(luò)攻擊網(wǎng)絡(luò)安全

2020-11-17 09:15:21

ColabJupyterPython

2021-06-17 07:47:03

軟件架構(gòu)分層

2019-12-18 15:05:17

運(yùn)營(yíng)商5G物聯(lián)網(wǎng)

2023-01-05 08:12:11

分層應(yīng)用代碼

2015-03-12 09:57:44

App StoreDNS宕機(jī)

2015-03-12 11:04:39

App StoreDNS宕機(jī)

2009-06-02 09:48:36

分層架構(gòu)PetShop.NET

2023-08-02 08:51:46

服務(wù)架構(gòu)分層架構(gòu)

2023-04-07 14:04:51

AI

2024-03-29 12:50:00

項(xiàng)目分層模型

2020-08-12 09:44:10

AI 數(shù)據(jù)人工智能

2023-06-16 13:34:00

軟件架構(gòu)模式

2023-10-26 16:02:04

線程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 欧美一级特黄aaa大片在线观看 | 日韩视频一区二区 | 亚洲日本欧美 | 亚洲日本国产 | 国产在线一区观看 | 欧洲一级毛片 | av在线天堂 | 人人澡人人射 | 一区二区三区亚洲视频 | 精品国产一区二区三区日日嗨 | 成人av网站在线观看 | 国产亚洲一区二区在线观看 | 九九亚洲| 久草热8精品视频在线观看 午夜伦4480yy私人影院 | 国产三级 | 久精品久久 | 亚洲欧美日韩精品久久亚洲区 | www.色综合 | 伊人色综合久久久天天蜜桃 | 成人欧美一区二区三区视频xxx | 日韩在线一区二区 | 羞羞视频免费在线观看 | 国产精品成人一区二区三区 | 国内精品久久精品 | 久久国产精品72免费观看 | 免费一区二区在线观看 | 免费看欧美一级片 | 成人免费精品 | 国产成人精品久久 | 亚洲综合在线一区 | www.狠狠操| 成人h动漫精品一区二区器材 | 国内精品久久久久久影视8 最新黄色在线观看 | 午夜精品久久久久久久久久久久久 | 久久久久免费 | 91精品国产综合久久久动漫日韩 | 一级视频在线免费观看 | 久草青青 | 日韩精品在线免费 | 一区二区久久 | 不卡一二区 |