go-clean-template - Golangサービスのクリーンなアーキテクチャテンプレート

(Clean Architecture template for Golang services)

Created at: 2021-01-18 17:29:43
Language: Go
License: MIT

クリーンテンプレートに移動

クリーンテンプレートに移動

Golangサービスのクリーンなアーキテクチャテンプレート

通知表に行く ライセンス リリース codecov

概要

テンプレートの目的は、次のことを示すことです。

  • プロジェクトを整理し、それがスパゲッティコードに変わるのを防ぐ方法
  • 独立性、クリーン性、拡張性を維持するためにビジネスロジックを保存する場所
  • マイクロサービスが成長したときに制御を失わないようにする方法

ロバートマーティン(別名アンクルボブ)の原則を使用します。

Go-clean-templateは、 Evroneによって作成およびサポートされています。

コンテンツ

クイックスタート

ローカル開発:

# Postgres, RabbitMQ
$ make compose-up
# Run app with migrations
$ make run

統合テスト(CIで実行可能):

# DB, app + migrations, integration tests
$ make compose-up-integration-test

プロジェクト構造

cmd/app/main.go

構成とロガーの初期化。次に、メイン関数はで「続行」し

internal/app/app.go
ます。

config

構成。最初に

config.yml
が読み取られ、次に環境変数が一致する場合はyaml構成を上書きします。構成構造はにあり
config.go
ます。タグを使用
env-required: true
すると、値を指定する必要があります(yamlまたは環境変数のいずれかで)。

構成には、cleanenvライブラリを選択しました。GitHubには星があまりありませんが、シンプルですべての要件を満たしています。

yamlから構成を読み取ることは、12の要素のイデオロギーと矛盾しますが、実際には、ENVから構成全体を読み取るよりも便利です。デフォルト値はyamlであり、セキュリティに敏感な変数はENVで定義されていると想定されています。

docs

Swaggerのドキュメント。スワッグライブラリによって自動生成されます。自分で修正する必要はありません。

integration-test

統合テスト。これらは、アプリケーションコンテナの隣にある別のコンテナとして起動されます。go-hitを使用してRestAPIをテストすると便利です。

internal/app

ファイルには常に1つのRun関数があり、これはメイン

app.go
関数を「継続」します。

これは、すべての主要なオブジェクトが作成される場所です。依存性注入は、「New ...」コンストラクターを介して行われます(依存性注入を参照)。この手法により、依存性注入の原則を使用してアプリケーションを階層化できます。これにより、ビジネスロジックが他のレイヤーから独立します。

次に、サーバーを起動し、selectのシグナルが正常に完了するのを待ちます。成長し始めたら

app.go
、それを複数のファイルに分割できます。

多数の注入には、ワイヤーを使用できます。

この

migrate.go
ファイルは、データベースの自動移行に使用されます。移行タグ付きの引数が指定されている場合に含まれます。例えば:

$ go run -tags migrate ./cmd/app

internal/controller

サーバーハンドラーレイヤー(MVCコントローラー)。テンプレートには2つのサーバーが表示されます。

  • RPC(トランスポートとしてのRabbitMQ)
  • REST http(Ginフレームワーク)

サーバールーターは同じスタイルで書かれています:

  • ハンドラーは、アプリケーションの領域ごとにグループ化されます(共通の基準によって)
  • グループごとに、独自のルーター構造が作成され、そのプロセスパスのメソッドが作成されます。
  • ビジネスロジックの構造は、ハンドラーによって呼び出されるルーター構造に挿入されます。

internal/controller/http

シンプルなRESTバージョン管理。

http/v2
v2の場合、同じコンテンツのフォルダーを追加する必要があります。そして、ファイル
internal/app
に次の行を追加します。

handler := gin.New()
v1.NewRouter(handler, t)
v2.NewRouter(handler, t)

Ginの代わりに、他のhttpフレームワークや標準

net/http
ライブラリを使用することもできます。

v1/router.go
ハンドラーメソッド以上に、swagを使用してSwaggerドキュメントを生成するためのコメントがあります

internal/entity

ビジネスロジック(モデル)のエンティティは、任意のレイヤーで使用できます。たとえば、検証のためのメソッドもあります。

internal/usecase

ビジネスの論理。

  • メソッドは、アプリケーションの領域ごとにグループ化されています(一般的に)
  • 各グループには独自の構造があります
  • 1つのファイル-1つの構造

リポジトリ、webapi、rpc、およびその他のビジネスロジック構造がビジネスロジック構造に注入されます(依存性注入を参照)。

internal/usecase/repo

リポジトリは、ビジネスロジックが機能する抽象ストレージ(データベース)です。

internal/usecase/webapi

これは、ビジネスロジックが機能する抽象的なWebAPIです。たとえば、ビジネスロジックがRE​​STAPIを介してアクセスする別のマイクロサービスである可能性があります。パッケージ名は目的により異なります。

pkg/rabbitmq

RabbitMQ RPCパターン:

  • RabbitMQ内にルーティングはありません
  • 1つの排他キューがバインドされているExchangeファンアウトが使用されます。これは、最も生産的な構成です。
  • 接続が失われたときに再接続します

依存性注入

外部パッケージへのビジネスロジックの依存性を取り除くために、依存性注入が使用されます。

たとえば、Newコンストラクターを使用して、ビジネスロジックの構造に依存関係を挿入します。これにより、ビジネスロジックが独立(および移植可能)になります。

usecase
パッケージに変更を加えることなく、インターフェースの実装をオーバーライドできます。

package usecase

import (
    // Nothing!
)

type Repository interface {
    Get()
}

type UseCase struct {
    repo Repository
}

func New(r Repository) *UseCase{
    return &UseCase{
        repo: r,
    }
}

func (uc *UseCase) Do()  {
    uc.repo.Get()
}

また、モックの自動生成(たとえば、モックを使用を実行し、単体テストを簡単に作成できるようになります。

あるコンポーネントを別のコンポーネントに常に変更できるようにするために、特定の実装に縛られることはありません。新しいコンポーネントがインターフェイスを実装する場合、ビジネスロジックで何も変更する必要はありません。

クリーンなアーキテクチャ

重要なアイデア

プログラマーは、ほとんどのコードが記述された後、アプリケーションに最適なアーキテクチャーを実現します。

優れたアーキテクチャにより、決定を可能な限り遅らせることができます。

主な原則

依存性逆転の原則(SOLIDと同じもの)は、依存性逆転の原則です。依存関係の方向は、外層から内層に向かっています。このため、ビジネスロジックとエンティティはシステムの他の部分から独立したままです。

したがって、アプリケーションは内部と外部の2つの層に分割されます。

  1. ビジネスロジック(Go標準ライブラリ)。
  2. ツール(データベース、サーバー、メッセージブローカー、その他のパッケージおよびフレームワーク)。

クリーンなアーキテクチャ

ビジネスロジックを備えた内層はクリーンである必要があります。そうすべき:

  • 外層からのパッケージのインポートはありません。
  • 標準ライブラリの機能のみを使用してください。
  • インターフェイス(!)を介して外層を呼び出します。

ビジネスロジックは、Postgresや特定のWebAPIについて何も知りません。ビジネスロジックには、抽象データベースまたは抽象WebAPIを操作するためのインターフェイスがあります。

外層には他の制限があります。

  • このレイヤーのすべてのコンポーネントは、互いの存在を認識していません。あるツールから別のツールを呼び出す方法は?直接ではなく、ビジネスロジックの内部層を介してのみ。
  • 内層へのすべての呼び出しは、インターフェース(!)を介して行われます。
  • データは、ビジネスロジックに便利な形式で転送されます(
    internal/entity
    )。

For example, you need to access the database from HTTP (controller). Both HTTP and database are in the outer layer, which means they know nothing about each other. The communication between them is carried out through

usecase
(business logic):

    HTTP > usecase
           usecase > repository (Postgres)
           usecase < repository (Postgres)
    HTTP < usecase

The symbols > and < show the intersection of layer boundaries through Interfaces. The same is shown in the picture:

例

Or more complex business logic:

    HTTP > usecase
           usecase > repository
           usecase < repository
           usecase > webapi
           usecase < webapi
           usecase > RPC
           usecase < RPC
           usecase > repository
           usecase < repository
    HTTP < usecase

Layers

例

Clean Architecture Terminology

  • Entities are structures that business logic operates on. They are located in the

    internal/entity
    folder. In MVC terms, entities are models.

  • Use Cases is business logic located in

    internal/usecase
    .

ビジネスロジックが直接対話するレイヤーは、通常、インフラストラクチャレイヤーと呼ばれます。これらは、リポジトリ

internal/usecase/repo
、外部WebAPI
internal/usecase/webapi
、任意のpkg、およびその他のマイクロサービスです。テンプレートでは、インフラストラクチャパッケージは内にあり
internal/usecase
ます。

必要に応じて、エントリポイントの呼び出し方法を選択できます。オプションは次のとおりです。

  • コントローラ(この場合)
  • 配達
  • 輸送
  • ゲートウェイ
  • エントリポイント
  • 主要な
  • 入力

追加のレイヤー

Clean Architectureのクラシックバージョンは、大規模なモノリシックアプリケーションを構築するために設計されており、4つのレイヤーがあります。

元のバージョンでは、外側のレイヤーはさらに2つに分割されており、これらも相互に依存関係が逆転し(内側に向けられ)、インターフェイスを介して通信します。

複雑なロジックの場合、内層も2つに分割されます(インターフェイスが分離されています)。


複雑なツールは、追加のレイヤーに分割できます。ただし、本当に必要な場合にのみレイヤーを追加する必要があります。

代替アプローチ

クリーンアーキテクチャに加えて、オニオンアーキテクチャヘキサゴナルポートとアダプタ)はそれに似ています。どちらも依存性逆転の原則に基づいています。 ポートとアダプタはCleanArchitectureに非常に近く、違いは主に用語にあります。

同様のプロジェクト

便利なリンク