在開始實作 Handler 之前,我們先來討論一下程式碼的職責切分。
在軟體設計中,有一個重要的原則叫做「單一職責原則」(Single Responsibility Principle, SRP)。
這個原則指出,每個模組或類別應該只有一個改變的理由。
換句話說,一個類別應該只負責一件事,這樣可以讓程式碼更容易維護和擴展。
我們將以處理一個 API Request 為例,來說明專案內的職責切分。
我們有一個 API 端點 api/user/register
,用來註冊使用者。
負責接收 HTTP 請求,解析請求參數,並將請求轉發給 Controller。
internal/http/handle_api.go
func registerAPIRoutes(r gin.IRouter, app *application.Application) {
registerAPIUserRoutes(r.Group("user"), app)
}
func registerAPIUserRoutes(r gin.IRouter, app *application.Application) {
uc := controller.NewUserController()
r.POST("register", uc.Register(app.UseCase.User.Register))
}
負責接受來自 Handler 的請求,將請求整理成為 usecase 所需的格式,並調用 usecase,最後將結果回傳給 Handler。
internal/controller/user.go
func (ctrl *UserController) Register(usecase *register.UseCase) gin.HandlerFunc {
return func(c *gin.Context) {
// 解析請求參數
// 呼叫 usecase
// 回傳結果
}
負責處理業務邏輯,並與 repository 或 service 互動以存取資料。
internal/usecase/api/user/register.go
func (uc *UserUseCase) Execute(ctx context.Context, input Input) (*Output, error) {
// 業務邏輯處理
// 與 repository 或 service 互動
return &Output{}, nil
}
負責組合各個模組,並將它們注入到需要的地方。
internal/application/application.go
func New(cfg *config.Config) (*Application, error) {
... // 省略其他初始化程式碼
app := &Application{
...
}
app.UseCase = NewUseCase(app)
return app, nil
}
這樣的職責切分可以確保每個模組都有明確的責任範圍,並且彼此之間的依賴關係清晰。這樣可以讓程式碼更容易維護和擴展,並且提高程式碼的可讀性和可測試性。
在這一章中,我們討論了程式碼的職責切分,並以一個 API Request 為例,說明了專案內各個模組的職責範圍。
透過清晰的職責切分,我們可以讓程式碼更容易維護和擴展,並提高程式碼的可讀性和可測試性。
在接下來的章節中,我們將進一步探討如何實作這些模組,並確保它們能夠協同工作。
以上程式碼的完整內容可以到 Github 觀看