分層架構是運用最為廣泛的架構模式,幾乎每個軟體系統都需要經過層來隔離不同的關注點,以此應對不同需求的變化,使得這種變化可以獨立進行;各個層、甚至同一層中的各個元件都會以不同速率發生變化。
這裡所謂的「以不同速率發生變化」,其實就是引起變化的原因各有不同,這正好是單一職責原則(single-responsibility principle,srp)的體現。即「乙個類應該只有乙個引起它變化的原因」,換言之,如果有兩個引起類變化的原因,就需要分離。
單一職責原則可以理解為架構原則,這時要考慮的就不是類,而是層次。例如網路七層協議是乙個定義的非常好的、經典的分層架構,簡單、易於學習理解,最終被廣泛使用進而大大推動了網路通訊的發展。
通常情況下,我們會把軟體系統分為這幾層:ui層、應用獨有的業務邏輯、領域普通的業務邏輯、資料庫等。
接下來,還有什麼不同原因的變更呢?答案正是這些業務邏輯本身!在每一層內部,不同的業務場景發生變化的原因、頻次也都不同,不同的場景我們分別定義為業務用例。由此,我們可以總結出乙個模式:在將系統水平切分成多個分層的同時,按用例將其切分成多個垂直切片。這樣做的好處就是對單個用例的修改並不會影響其他用例。
如果我們同時對支援這些用例的ui和資料庫也進行了分組,那麼每個用例使用各自的ui表現與資料庫,這樣就做到了自上而下的解耦。另一方面,有層次就有依賴。在osi協議中,上層透明的依賴下層。但是在軟體架構中,我們更強調「依賴抽象」。即元件a依賴b的功能,我們的做法是在a中定義其需要用到的介面,由b去實現對應介面能力,這樣就做到了可插拔,將來我們可以把b替換為同樣實現了介面能力的元件c而對系統不會造成影響。
分層架構中給人的感覺是每一層都同樣重要,但如果我們把關注的重點放在領域層,同時把依賴關係按照業務由重到輕形成乙個以領域層為中心的環,即演變為一種整潔的架構風格。這裡不是說其他層不重要,僅僅是為了凸顯承載了業務核心的領域能力。
整潔架構最主要原則是依賴原則,它定義了各層的依賴關係,越往裡,依賴越低,**級別越高。外圓**依賴只能指向內圓,內圓不知道外圓的任何事情。一般來說,外圓的宣告(包括方法、類、變數)不能被內圓引用。同樣的,外圓使用的資料格式也不能被內圓使用。
整潔架構各層主要職能如下:
entities:實現領域核心心業務邏輯,它封裝了企業級的業務規則。乙個entity可以使乙個帶方法的物件,也可以是乙個資料結構和方法集合。一般我們建議建立充血模式。
inte***ce adapters:它把適用於 use cases 和 entities 的資料轉換為適用於外部服務的格式,或把外部的資料格式轉換為適用於 use casess 和 entities 的格式。
frameworks and drivers:這是實現所有前端業務細節的地方,ui,tools,frameworks 等以及資料庫等基礎設施。
我們把整潔架構的外部依賴按照其輸入輸出功能、資源型別進行整合。將儲存、中介軟體、與其它系統的整合、http呼叫分別暴露乙個埠。則會演變成下面的架構圖。
系統能平等地被使用者、其它程式、自動化測試或指令碼驅動,也可以獨立於其最終的執行時裝置和資料庫進行開發和測試。
該架構由埠和介面卡組成,所謂埠是應用的入口和出口,在許多語言中,它以介面的形式存在。例如以取消訂單為例,「傳送訂單取消通知」可以被認為是乙個出口埠,訂單取消的業務邏輯決定了何時呼叫該埠,訂單資訊決定了埠的輸入,而埠為上游的訂單相關業務遮蔽了其實現細節。
介面卡分為兩種,主介面卡(別名driving adapter)代表使用者如何使用應用,從技術上來說,它們接收使用者輸入,呼叫埠並返回輸出。rest api是目前最常見的應用使用方式,以取消訂單為例,該介面卡實現rest apide endpoint,並呼叫入口埠orderservice,當然service內部可能傳送ordercancelled事件。同乙個埠可能被多種介面卡呼叫,本場景的取消訂單也可能會被實現訊息協議的driving adapter呼叫以便非同步取消訂單。
次介面卡(別名driven adapter)實現應用的出口埠,向外部工具執行操作,例如向mysql執行sql,儲存訂單;使用elasticsearch的api搜尋產品;使用郵件/簡訊傳送訂單取消通知。有別於傳統的分層形象,形成乙個六邊形,因此也會被稱作六邊形架構。
springcloud(2) 服務註冊與發現
目錄例項 服務端客戶端 測試 集群 1 新增依賴 org.springframework.cloud spring cloud starter netflix eureka client 2 配置檔案 3 啟動類新增 enablediscoveryclient 4 controller restco...
springcloud(2)微服務之間的相互呼叫
呼叫其他微服務 component public class productclientribbon ribbon 客戶端,通過 resttemplate 訪問 http product data service products 而 product data service 既不是網域名稱也不是i...
SpringCloud 2 搭建服務端介面
服務端要進eureka註冊中心,所以引入資料庫 spring 等依賴之外還需要引入eureka客戶端的依賴,如下 org.springframework.cloud spring cloud starter netflix eureka client mybatis config location ...