iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 12
0
Modern Web

Go into Web!系列 第 12

Day12 | 當需求遇到 Clean Architecture

今天我們不會講太多關於 Clean Architecture 的概念,因為目前有許多文章都分享過了,今天主要是要跟大家分享當一個需求下來時,怎麼將需求拆分之後使用 Clean Architecture 的概念設計架構,就讓我們開始吧!

背景

Clean Architecture 是由 Robert C. Martin 於 2000 年所提出的一種架構,此架構主要的精神著重於描述 分層減少相依性 的重要性,詳細的介紹可以參考 這裡

本次分享的架構

我目前所採用的 clean architecture 是採用 bxcodec這個專案 所使用的架構,其架構的中心思想也是參考 Robert 所提出的原始版本,其改良的原因在這裡

架構

如上圖,此架構主要分成四個階層依序為

  • Model Layer
  • Repository Layer
  • Service Layer
  • Delivery Layer

以下會分別對這四個階層做介紹

Model Layer

用於定義資料格式與屬性,此階層所定義的物件會在其他三層都會用到。

Repository Layer

用於與外部 service 互動的 adapter,例如要與 mariadbmongo 或是 redis 等 data storage 進行互動,就將方法封裝在此階層內。

Service Layer

用於封裝商業邏輯方法,在系統內有用到的邏輯判斷或是演算法都會放在此階層內。

Delivery Layer

用於封裝接口給外部使用者使用的方法,例如要提供 restgRPC 或是 command line 的方法都會封裝在此階層內。

實際案例

需求

規劃一個簡單的 會員系統,其中要包含 註冊登入 的功能並且開放 RESTful API 給前端存取

拆分階層

定義 Model Layer 的 Entity

首先,我們可以思考一個會員系統內最基本的單位為 使用者,不管使用任何功能都會與使用者有關,因此可以得知 Model Layer 內一定會有 使用者,因此在這邊我們可以將其抽離出來,接著思考基本的使用者會有什麼樣的資訊,最最最基本的使用者可以包含 idusernamepassword 這三個資訊,其中 id 是唯一值,以下為 使用者的結構。

type User struct {
	ID       string `json:"id"`
	Username string `json:"username"`
	Password string `json:"password"`
	Email    string `json:"email"`
	Phone    string `json:"phone"`
}

依照資料來源定義 Repository Layer

接著可以思考看看,Model Layer 的資料要存放在哪裡與如何取得,我們可以透過封裝 使用者 CURD 的方法實現。

type Repository interface {
	GetUserList(map[string]interface{}) ([]*User, error)
	GetUser(in *User) (*User, error)
	CreateUser(in *User) (*User, error)
	ModifyUser(in *User, data map[string]interface{}) (*User, error)
	DeleteUser(in *User) error
}

依照邏輯切出 Service Layer

需求有定義的很清楚,要實現 註冊登入 的功能,因此這邊可以將這兩個方法的邏輯封裝成 RegisterLogin 方法,可以在方法內存取 Repository Layer 的方法並進行運算。

type Service interface {
	Login(id, password string) (*User, error)
	Register(in *User) (*User, error)
}

依照對外提供的方法切出 Delivery Layer

在需求最後有提到要開放 RESTful API 給前端存取,因此我們可以呼叫 Service LayerRegisterLogin 兩個方法並提供 POST /api/v1/user/registerPOST /api/v1/user/login 的方法供前端存取。

type RestfulHandler interface {
	Login(c *gin.Context) error
	Register(c *gin.Context) error
}

透過以上的方法可以將整體需求實作完成,每一階層都有自己專門負責的事項。

小結

今天透過範例理解了怎麼透過 clean architecture需求 轉換為程式的架構,這也是我目前開發時所使用的方法,希望對大家有幫助!

明天就讓我們利用今天所描述的範例透過 golang 實作出來吧!

參考


上一篇
Day11 | 淺談 REST
下一篇
Day13 | log 輸出的重要性
系列文
Go into Web!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言