Golangのディレクトリ構成について
実務にてGolangでclean architectureに基づいて取り組んでいるが、usecase層の増加が自分で書いていて気がかりになったので調べたものをまとめていく
現状
層の役割
-
infrastructure層(Framwork&Drivers)
外部との通信- Web
外部とのやりとりなのでAPIのエンドポイントの設定 - DB
MySQLやPostgreSQLなどデータベースと接続する
- Web
-
interfaces層(adapter)
上位レイヤーを下位レイヤーを橋渡しする役割- controllers
他ではhandlerで実装されていることが多い気がする
下位レイヤーに繋ぐ - gateways
上位レイヤーを繋ぐinterfaceの役割で使用している - presenters
実務では扱っていないが、Webで扱いやすい値にラップする役割があると思っている
- controllers
-
usecase層(application)
アプリケーション固有のビジネスロジックが描かれる- usecase
主にビジネスロジックを置いておく←ここが今の問題箇所 - repository
usecase層から上位のデータベースへデータを取得などするためのinterface
- usecase
等他レイヤーと比べて多数の概念が存在する
- domain層(entities)
データを永続化させる
大前提として
clean architectureはそれぞれの層以外は他の実装内容は知ることはあってはいけない。
詳細を知ってしまうと、変更があった際に他のレイヤーへの影響が大きくなってしまい概念から破綻してしまうと思う。
必ず依存関係は一方向でないといけないがそれだとそもそもシステムが成り立たないと思うので依存関係逆転の法則というものが存在する。これは下位レイヤーが上位レイヤーを呼び出したい時に抽象を用いて実装を可能にする。この際もインターフェイスの役割を持っているものはお互いの実装内容は知ってはいけない。
結局のところ
実装していくとロジックの部分は増えていってしまうのかなと思っている
またまとまってくれば更新してベストプラクティスを見つけていきたい
アーキテクチャに沿って記述していてもこの関数は全体で使用する可能性があると思うものは
/utils
などのルート階層に配置してみた。
例としてこの/utilsを各層から呼び出せるが、このディレクトリから呼び出すことをない、つまり依存することはないようにする。
/domainに配置しないのは、データとして値の生成などは行うがデータの永続化には関係なくすため。
レスポンス用に装飾する際の関数やメソッドをinterfaces/presenters層に加えるべきか、domain層でメソッドとして扱うか迷う。
データの永続化と定義していたのでdomain層では扱わないようにした。
controllers -> interactor -> presenters -> interactorといった大まかなデータの流れとしてみる。
interactor -> presentersに関してはinterface{}を活用して依存関係を解消した。
現在個人的にアプリを作成していっている中で思うことがあれば引き続き記述を追加していく。
presenter層の実装についてはレスポンスの値を見やすいように生成するのであればこちらに
データ自身を操作するのであればdomain層のメソッドに追加する
ロジックでもほぼ普遍的なものをdomain層に割り当てる
GraphQLやgRPCを採用する場合はcontroller層がかなりさっぱりする(ほぼいらない気もする)のでプロジェクトに応じて変更する感じになりそう
それでもこれはサンプルかつモノリス想定で構築したのみの所感