1. 程式人生 > 其它 >專案目錄結構

專案目錄結構

原文地址

什麼是DDD?

DDD 是 Domain-Driven Design 的縮寫。 其主要的思想是,我們在設計軟體時,先從業務出發,理解真實的業務含義,將業務中的一些概念吸收到軟體建模中來,避免造出“大而無用”軟體。也避免軟體設計沒有內在聯絡,否則一團散沙,無法繼續演進。

為什麼要使用DDD?

過去,最常用的架構是三層架構,最典型的是MVC。三層架構的問題就是控制層依賴業務層,業務層又依賴資料層。特別是在資料層為貧血模型下,會讓業務層的程式碼高速膨脹。在維護過程中,改了一點需求就會引發意想不到的bug,修復bug又會引起其他的bug。

貧血模型和充血模型

貧血模型

所謂貧血模型,是指Model 中,僅包含狀態(屬性),不包含行為(方法),採用這種設計時,需要分離出DB層,專門用於資料庫操作。

充血模型

Model 中既包括狀態,又包括行為,是最符合面向物件的設計方式。

業務層設計

我們在寫業務程式碼的時候,最終要的往往在業務層,控制層就是最一些引數校驗處理,資料層就是持久化資料。業務邏輯集中在業務層,在三層就夠中業務層往往依賴資料層,吧orm的model物件拿到業務層使用,這是出bug概率最大的問題。那我們能不能做出設計,在業務層,既不依賴控制層也不依賴資料層呢?

我們使用反向依賴的方式,讓資料層依賴業務層。

比如我們要查詢一些使用者的訂單資訊

type User struct {
    Id int 
    Name string
    Password string
    Age uint8
}

type Order struct {
    Id int
    Good string
    PayTime time.Time
}

type UserRepo interface {
    GetUsers(ctx context.Context,name string) ([]*User,error)
}

type OrderRepo interface {
    GetOrders(ctx context.Context,userId int) ([]*Order,error)
}

type UserUseCase struct {
    ur UserRepo
    or OrderRepo
}

func NewUserUseCase(ur UserRepo,or OrderRepo) *UserUseCase {
    return &UserUseCase{
        ur:ur,
        or:or,
    }
}

func (uuc *UserUseCase) GetOrders(ctx context.Context,name string) ([]*Order,error) {
    users,err := uuc.ur.GetUsers(ctx,name)
    if err != nil || len(users) == 0 {
        return fmt.Errorf("xxx%w",err)
    }
    userId := users[0].Id
    return uuc.or.GetOrders(ctx,userId)
}

在上面的例子中,在GetOrders方法中呼叫介面Repos中的方法,把業務程式碼寫完之後,進行單元測試我們只要mock實現各個repo的介面就好。然後再持久層(資料層)實現這些repo方法,在方法中把PO轉成DO。在控制層使用NewUserUseCase建立UseCase。進行呼叫吧DO轉化成DTO返回。

當然在業務複雜時,usecase的方法要簡單,吧邏輯都封裝到domain service中。

DTO DO和PO

DTO: Data Transfer Object的縮寫。用於表示一個數據傳輸物件。DTO 通常用於不同服務或服務不同分層之間的資料傳輸。

BO: Business Object 的縮寫,用於表示一個業務物件。

PO: Persistant Object縮寫。用於資料庫中一條記錄對映成struct。

專案例子

專案例子可以檢視 beer-shop 專案,它是基於微服務框架kratos 實現的微服務專案。