iT邦幫忙

2025 iThome 鐵人賽

DAY 8
0
Software Development

Go Clean Architecture API 開發全攻略系列 第 8

Usecase 層的職責:編排你的核心業務邏輯

  • 分享至 

  • xImage
  •  

Usecase 層是我們應用程式的核心,它體現了所有的業務流程。它的職責是:

  1. 接收來自 Controller 的簡單指令和數據(DTOs)。
  2. 調度一個或多個 Repository 和 Service,來執行一系列操作。
  3. 實現純粹的、與技術無關的業務規則。
  4. 將執行結果回傳給 Controller。

第一步:定義 usecase 的輸入與輸出 (DTOs)

一個設計良好的 usecase 應該有明確的輸入(Input)和輸出(Output)資料結構。這使得它的「契約」非常清晰。

internal/usecase/api/user/register/register.go

// 定義 usecase 的輸入與輸出
type Input struct {
	email    string
	password string
}

type Output struct {
  AccessToken string
}

第二步:定義 usecase 的結構

接下來,我們定義 usecase 結構體,它包含了執行此業務所需的所有「依賴」。

internal/usecase/api/user/register/register.go

// 定義 usecase 需要的依賴介面
type repository interface {
	CheckEmailIsExists(email string) (bool, error)
	CreateUser(email, hashedPassword string) (int, error)
}

type password interface {
	Hash(password string) (string, error)
}

type token interface {
	GenerateAccessToken(userID int) (string, error)
}

// 定義 usecase
type UseCase struct {
	repository repository
	password   password
	token      token
}

func NewUseCase(repository repository, password password, token token) *UseCase {
	return &UseCase{
		repository: repository,
		password:   password,
		token:      token,
	}
}

第三步:實現 usecase 的核心邏輯

接下來,我們實現 Execute 方法,這是 usecase 的核心。它負責安排所有的業務邏輯。


func (u *UseCase) Execute(ctx context.Context, input Input) (*Output, error) {
	isExists, err := u.repository.CheckEmailIsExists(input.email)
	if err != nil {
		return nil, err
	}

	if isExists {
		return nil, errors.New("email is already registered")
	}

	hashedPassword, err := u.password.Hash(input.password)
	if err != nil {
		return nil, err
	}

	userID, err := u.repository.CreateUser(input.email, hashedPassword)
	if err != nil {
		return nil, err
	}

	accessToken, err := u.token.GenerateAccessToken(userID)
	if err != nil {
		return nil, err
	}

	return &Output{
		AccessToken: accessToken,
	}, nil
}

第四步:Usecase 的純粹性

現在,請仔細觀察我們剛剛寫好的 Execute 方法。你會發現一個美妙的事實:這段程式碼裡,沒有任何與外部技術相關的內容。

  • 沒有 gin.Context
  • 沒有任何 HTTP Header 或 Http Query String 或 Http Path 或 JSON 相關的處理。
  • 沒有任何資料庫相關的程式碼。
  • 沒有任何第三方服務的 SDK 調用。

它只認識 context.Context、以及幾個抽象的介面。這就是六角形架構帶給我們的最大好處:一個與框架無關、高度可測試、可獨立演進的核心業務邏輯層。

總結

在這一章中,我們學會了如何設計和實現一個乾淨的 Usecase 層。
這個層次負責編排我們的核心業務邏輯,並且與外部技術細節完全解耦。
這使得我們的應用程式更加模組化、易於測試和維護。

以上程式碼的完整內容可以到 Github 觀看


上一篇
Gin 框架開發實戰(二):職責切分
下一篇
身份驗證詳解 (一):安全的密碼雜湊 (Hashing) 與處理
系列文
Go Clean Architecture API 開發全攻略9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言