#はじめに
特にルールがない場合に、個人的に使用しているバックエンドアプリケーションでのディレクトリ構造です。レイヤードアーキテクチャを意識し、各ディレクトリの役割を明確化し、わかりやすくしてあります。
こういったレイヤー構造はチーム内で共通認識を持つために存在するので、すでに明確なルールが存在する場合はそれに準じたほうが良いかと思います。
あくまでも一例として参考にしてもらえると幸いです。
おおまかなディレクトリ構造
.
├── Controller
├── DTO
├── Entity
├── Model
├── Repository
├── Service
└── UseCase
上記に加え、各フレームワークが生成するディレクトリが加わるかと思います。
各ディレクトリの役割
Controller
Webからのリクエストを扱うコントローラです。リクエストを受け取りレスポンスを返す役目です。
たいていフレームワークに依存します。
DTO
ControllerからUseCase、UseCaseからControllerに渡すデータを定義します。
リクエストデータの実体になったり、Viewテンプレートに渡して表示に使用したりします。
UseCase
ユースケースを扱います。たいていモデルを複数使用する形になります。
Webでの表示に使用するデータもここで組み立てます。
大抵はDTOのコンストラクタにモデルから受け取ったデータを指定するだけになりますが…。
Model
ビジネスロジックを持ちます。可能な限りフレームワークへの依存を排除します。
また、自身が依存するRepositoryやServiceのInterface、Entityを定義します。
一言でクラスを説明できるくらいの粒度でクラスは作成します。基本、publicメソッドは1つです。
Repository
データベースへのCRUDを扱います。Entityを受けたり返したりします。
フレームワークに依存します。Repositoryクラスはテーブル単位ではなく、モデル単位で作成するとよいです。
データの取得からEntityへの加工、またはEntityからデータの保存を行います。
Entity
Repositoryで返されるオブジェクトを定義します。ORMに依存しない形にします。
Service
外部サービスへの依存が強いものを扱います。AWSなどのクラウド系へのアクセスや外部APIを使用するクラスを作成します。
依存関係
例題
AWSのDynamoDBに保管してある所属IDのリストに属するメンバーの一覧を取得する。
クラス図
呼び出しシーケンス
この構造にすると何が嬉しいのか
- UseCaseとModelを切り出してライブラリ化することが可能です。
- そのため、WebフレームワークやORMの影響を受けずに、ロジックだけ先行で開発することが可能になります。
- チーム内の認識が統一しやすくなります
- 明示されたルールが有ると、それを元に議論しやすくなるため、より良い設計にたどり着くかもしれません。
補足
- ModelとかEntityと言う名称はフレームワークやライブラリと競合する可能性があります。
- その場合は、こっち側の名称をLogicとかDataObjectなどに変えるとよいかと思います。