自分流レイヤードアーキテクチャを意識したバックエンドアプリケーションのディレクトリ構造

#はじめに
特にルールがない場合に、個人的に使用しているバックエンドアプリケーションでのディレクトリ構造です。レイヤードアーキテクチャを意識し、各ディレクトリの役割を明確化し、わかりやすくしてあります。
こういったレイヤー構造はチーム内で共通認識を持つために存在するので、すでに明確なルールが存在する場合はそれに準じたほうが良いかと思います。 
あくまでも一例として参考にしてもらえると幸いです。

# おおまかなディレクトリ構造

```
.
├── Controller
├── DTO
├── Entity
├── Model
├── Repository
├── Service
└── UseCase
```

上記に加え、各フレームワークが生成するディレクトリが加わるかと思います。

# 各ディレクトリの役割

## Controller
Webからのリクエストを扱うコントローラです。リクエストを受け取りレスポンスを返す役目です。
たいていフレームワークに依存します。

## DTO
ControllerからUseCase、UseCaseからControllerに渡すデータを定義します。
リクエストデータの実体になったり、Viewテンプレートに渡して表示に使用したりします。

## UseCase
ユースケースを扱います。たいていモデルを複数使用する形になります。
Webでの表示に使用するデータもここで組み立てます。
大抵はDTOのコンストラクタにモデルから受け取ったデータを指定するだけになりますが…。

## Model
ビジネスロジックを持ちます。可能な限りフレームワークへの依存を排除します。
また、自身が依存するRepositoryやServiceのInterface、Entityを定義します。
一言でクラスを説明できるくらいの粒度でクラスは作成します。基本、publicメソッドは１つです。

## Repository
データベースへのCRUDを扱います。Entityを受けたり返したりします。
フレームワークに依存します。Repositoryクラスはテーブル単位ではなく、モデル単位で作成するとよいです。
データの取得からEntityへの加工、またはEntityからデータの保存を行います。

## Entity
Repositoryで返されるオブジェクトを定義します。ORMに依存しない形にします。

## Service
外部サービスへの依存が強いものを扱います。AWSなどのクラウド系へのアクセスや外部APIを使用するクラスを作成します。


# 依存関係

## 例題
AWSのDynamoDBに保管してある所属IDのリストに属するメンバーの一覧を取得する。

### クラス図

```plantuml
	
@startuml
package Controller{
  class GetMemberListController{
    - useCase : GetMemberListUseCase
    + fromDynamoDB()
  }
}
package UseCase{
  class GetMemberListUseCase{
    - departmentIdListGetter : GetDepartmentIdList
    - memberListGetter : GetMemberList
    + fromDynamoDB() : GetMemberListData<List>
  }
  entity GetMemberListData{
    + id : int
    + name : string
  }
}
package Model {
  class GetDepartmentIdList{
    - service : GetDepartmentIdServiceInterface
    + get()
  }
  class GetMemberList{
    - repository: GetMemberListRepositoryInterface
    + get()
  }
  interface GetDepartmentIdServiceInterface{
    + get()
  }
  interface GetMemberListRepositoryInterface{
    + findByDepartmentId():Entity
  }
  entity Entity{
    + id : int
    + string : name
  }

}
package Service{
  class GetDepartmentIdService{
    + get()
  }
}
package Repository{
  class GetMemberListRepository{
    + findByDepartmentId():Entity
  }
}


GetMemberListUseCase <-u- GetMemberListController : 依存

GetDepartmentIdList <-u- GetMemberListUseCase : 依存
GetMemberList <-u- GetMemberListUseCase : 依存

GetMemberListRepositoryInterface <-u- GetMemberList : 依存
GetDepartmentIdServiceInterface <-u- GetDepartmentIdList : 依存

GetMemberListRepository -u-> GetMemberListRepositoryInterface : 実装
GetDepartmentIdService -u-> GetDepartmentIdServiceInterface : 実装


@enduml
```

# 呼び出しシーケンス
```plantuml
@startuml
Web -> GetMemberListController: リクエスト
GetMemberListController -> GetMemberListUseCase
GetMemberListUseCase -> GetDepartmentIdList
GetDepartmentIdList -> GetDepartmentIdServiceInterface
GetDepartmentIdList <- GetDepartmentIdServiceInterface
GetDepartmentIdList -> GetMemberListUseCase
GetMemberListUseCase -> GetMemberList
GetMemberList -> GetMemberListRepositoryInterface
GetMemberListRepositoryInterface -> GetMemberList
GetMemberList -> GetMemberListUseCase
GetMemberListUseCase -> GetMemberListController
GetMemberListController -> Web : レスポンス
@enduml

```

## この構造にすると何が嬉しいのか

- UseCaseとModelを切り出してライブラリ化することが可能です。
    - そのため、WebフレームワークやORMの影響を受けずに、ロジックだけ先行で開発することが可能になります。
- チーム内の認識が統一しやすくなります
    - 明示されたルールが有ると、それを元に議論しやすくなるため、より良い設計にたどり着くかもしれません。

## 補足

- ModelとかEntityと言う名称はフレームワークやライブラリと競合する可能性があります。
    - その場合は、こっち側の名称をLogicとかDataObjectなどに変えるとよいかと思います。