是按技術職責還是按領域職責劃分模組包? - Reddit

banq發表於2022-03-29

在構建 REST api 時,您會選擇:

選項 A:

├── controllers

│   ├── order.go

│   ├── region.go

│   └── user.go

├── models

│   ├── order.go

│   ├── region.go

│   └── user.go

└── repos

├── order.go

├── region.go

└── user.go




選項 B:

├── order

│   ├── order_controller.go

│   ├── order_entity.go

│   └── order_repo.go

├── region

│   ├── region_controller.go

│   ├── region_entity.go

│   └── region_repo.go

└── user

├── user_controller.go

├── user_entity.go

└── user_repo.go



這是如何在不妥協的情況下在鬆散耦合和高內聚之間找到平衡。
第一個選項適用於非常小范的專案,其中型別很少,“處理程式”很多,像“ToDo”應用程式,演示,單一職責命令列工具這樣的幼稚專案適合這種情況,因為凝聚力不會受到太大影響,因為有每個包中的東西很少。

現第二個適用於其他一切:
如果一旦您在這些目錄中擁有大量相同命名的.go檔案,那麼尋找單一型別的實現和跟蹤程式碼將變得非常笨拙。
兩打目錄和幾個檔案比幾個資料夾更容易推理,每個資料夾中有兩打檔案,每個資料夾都命名相同。

這就是為什麼我從不選擇第一種方法,因為隨著熵的增加,它幾乎總是蛻變為第二種方法,而且當我可以從那裡開始的時候,重新構建所有的東西是浪費時間的。
   
 

按團隊劃分
下面是我們團隊的標準佈局,我們有一個工具可以保證這一點。
我們的佈局是這樣的:

├── etc
│   └── pet-api.yaml
├── internal
│   ├── config
│   │   └── config.go
│   ├── handler
│   │   ├── cat_create_handler.go
│   │   ├── dog_create_handler.go
│   │   └── routes.go
│   ├── logic
│   │   ├── cat_create_logic.go
│   │   └── dog_create_logic.go
│   ├── svc
│   │   └── service_context.go
│   └── types
│       └── types.go
└── pet.go

  • etc是yaml配置檔案的資料夾
  • config包含配置的 Go 定義
  • handler包含路由的 HTTP 處理程式
  • logic包含每個處理程式的 biz 邏輯
  • svc是從外部傳入處理程式的服務上下文,例如資料庫例項。
  • types是定義請求和響應型別的資料夾


為什麼我把邏輯資料夾和handler處理程式分開,是因為我希望我們的團隊儘可能少地把HTTP請求的資訊傳遞給邏輯處理函式。

另外,所有資料夾的佈局是由goctl從下面的API定義檔案中生成的,命令是goctl api go -api demo.api -style go_zero -dir .

type (
    CatCreateRequest {
        Name string `path:"name"`
    }

    CatCreateResponse {
        Message string `json:"message"`
    }
)

type (
    DogCreateRequest {
        Name string `path:"name"`
    }

    DogCreateResponse {
        Message string `json:"message"`
    }
)

@server(
    prefix: v1
)
service pet-api {
    @handler CatCreateHandler
    post /pets/cats/:name(CatCreateRequest) returns (CatCreateResponse)

    @handler DogCreateHandler
    post /pets/dogs/:name(DogCreateRequest) returns (DogCreateResponse)
}


字首:v1將/v1新增到服務中的所有路由,它是可選的。

對於單體服務,我們會在內部下新增模型資料夾,用於資料訪問程式碼。

另外,goctl支援自定義生成行為的選項,比如命名風格、將請求分組到不同的包中,甚至將處理程式和邏輯分別壓縮到一個檔案中。

安裝:go install github.com/zeromicro/go-zero/tools/goctl@latest

   

六邊形架構
對於微型服務來說,擁有如下軟體包:

- cmd
— service_name
— mock_service
- internal
— entities
— errors
— repositories
—— database
—— fxrates_provider
— server
—— http
—— grpc
— usecases

  • cmd - 持有啟動你的服務的方法
  • http/grpc等在/server目錄下--你的服務的進入點
  • usecases--領域/業務邏輯層
  • mysql/firestone/其他一些api在/repositories目錄下--來自外部的任何資料
  • entities--建立並通過各層傳遞的模型
  • errors--全域性錯誤,使錯誤檢查更容易。


優點。
  • 沒有迴圈的依賴關係
  • 非常清楚地將邏輯分離出來
  • 只要滿足預期的介面,就可以互相替換層(你的老闆決定明天要支援http? 沒問題!)。
  • 更容易測試
  • 更容易用gomock來模擬介面
  • 更容易除錯(根據我的經驗,更少的麵條,更清晰的責任)。


缺點。
  • 一些重複的程式碼
  • 轉換為實體有時是件麻煩的事

相關文章