Featured image of post Spring中的Clean Architecture

Spring中的Clean Architecture

淺談Spring專案中如何實現Clean Architecture

參考影片:Clean Architecture with Spring by Tom Hombergs @ Spring I/O 2019

架構的目標

  • Facilitate Development
  • Facilitate Deployment
  • Facilitatte maintenance
  • keep software soft
  • keep frameworks of arm’s length
  • keep options open

架構的終極目標

The Goal of software Achitecture is to minimize the lifetime cost of the software

分層式(Layers)架構有什麼問題?

image-20230425103609358

分層架構是一種可靠的架構模式!但是如果沒有額外的限制,它們容易出現設計缺陷。

根據講者的經驗,我們有很多的架構是所謂的資料庫驅動設計(Database Driven design)

image-20230425104040987

在我們的Domain Layer,我們有Service Layer、Persistence Layer,裡面存在著我們的Entity以及JPA相關的一些資訊

模糊的界線(Blurred Boundaries)

image-20230425104746565

另一個關於Layer的議題是,我們通常會有一個工具類(utili)來封裝我們常用的一些函式庫,這些東西會在各層之間流竄,這樣會使得各層之間的關係越發模糊。

難以測試

image-20230425105152281

需要Mock很多東西,比如說Service、Repository。

許多功能被隱藏起來了

image-20230425105419213

假使我們有一個Order的系統,那我們所有對Order的CRUD都會集中在OrderService中,一旦這個方法有很多個,那麼很多方法(Functionality)就會被埋沒起來

那麼如何解決這些問題呢 ?

Do Circles Instead

image-20230425110140878

再議SOLID設計模式

image-20230425110249239

Dependency Inverision Principle

依賴反轉原則

image-20230425110509871

(左圖為Database Driven Development)

影片戳記時間

若要執行依賴反轉原則,那麼Domain層不應該依賴Persistence層,而是反轉過來,(Use Case等同於Service層),

這樣做的好處是什麼?我們可以選擇任何Code的依賴方向

Single Responsibility Priniciple

一個Class或一個Module只做一件事情

一個Class或一個Module只能有一個原因被修改(Change)

image-20230425115237259

image-20230425115334794

分層式架構下,若Persistence修改了,那麼Business層有很大機率也會連動修改,但在Clean Architecture的架構下,Persistence由於不處於最核心的部分(Entity),因此不需要一起改動

image-20230425115740567

image-20230425132945444

假使我們有一個Order Service,其中有三個user Roles,當其中一個User Roles改變後,我們就要去改動我們的Service

image-20230425133140173

但當我們把Service分割成不同的Use Cases,每一個Cases指對應一個Use Roles,那麼這個Use Case也只會有一個原因被修改

Service應該被切割成許多不同的Use Case(First-Class Citizens)

Only a Domain-Centric Architecture Allows Domian-Driven Design

Clean Architecture

image-20230425114053702

Hexagons

image-20230425133410510

六角架構是Clean Architecture的具現化

  • Input Port:對外暴露的API

use case class implements an input port, the input port is just a Java interface, then the use case class modifies the domain model

問題時間:這個應用程式在做什麼?

分層架構下,只透過Class名稱無法獲得有用的訊息

image-20230425134701498

六角架構中,將Service拆分成不同的Use Case,所有的職責會更加一目了然

image-20230425134819273

實作時間

Code連結:thombergs/buckpal

Summary

image-20230425143339079

image-20230425143423176

如何強迫我們使用這個架構

image-20230425143656605

image-20230425143713734

Licensed under CC BY-NC-SA 4.0