APIの役割
DDDでのAPIの役割
DDDのレイヤー構成では、APIはPresentation層に含まれます。Presentation層は、利用者や外部システムから要求を受け取り、Application Serviceを呼び出し、その結果を外部へ返します。
APIはHTTPリクエストとレスポンスを扱います。参加できるかどうかなどの業務上の判断は、Application Serviceを通してドメインモデルへ任せます。
具体例で整理する
例えば、フットサルNOWで参加者が募集の「参加する」を押すと、参加申請APIへリクエストが送られます。
APIは、リクエストから「募集ID」を受け取り、ログインしている利用者から「参加者ID」を取得します。その値を参加申請のApplication Serviceへ渡し、処理が完了したらHTTPレスポンスを返します。
- 1リクエストから募集IDを受け取る
- 2ログイン中の利用者から参加者IDを取得する
- 3参加申請のApplication Serviceを呼ぶ
- 4処理結果をHTTPレスポンスとして返す
コードで表す
Next.jsのRoute Handlerから、参加申請のApplication Serviceを呼び出す例です。
// src/app/api/recruitments/[recruitmentId]/participation/route.ts
export async function POST(
_request: Request,
context: { params: Promise<{ recruitmentId: string }> },
) {
// URLから募集IDを受け取る
const { recruitmentId } = await context.params;
// ログインしている利用者を取得する
const signedInUser = await requireSignedInUser();
// HTTPの入力から、参加申請のCommandを作る
const command: RequestParticipationCommand = {
recruitmentId,
participantId: signedInUser.id,
requestedAt: new Date(),
};
// 参加申請のApplication ServiceへCommandを渡す
await requestParticipationApplicationService.execute(command);
// 参加申請が完了したことをHTTPレスポンスで返す
return new Response(null, { status: 204 });
}このAPIは、参加申請に必要な値を用意し、IRequestParticipationApplicationServiceで決めた方法でApplication Serviceを呼びます。
APIに業務ルールを書かない
「申込期限を過ぎていないか」「同じ人が二重に申請していないか」「定員に達していないか」は、APIでは確認しません。これらは参加申請の業務ルールなので、募集のドメインモデルが確認します。
一方で、募集IDが文字列として渡されているかなど、リクエストとして受け取れる形式かを確認する処理はAPIに置けます。
ディレクトリで表す
src/
├── app/
│ └── api/
│ └── recruitments/
│ └── [recruitmentId]/
│ └── participation/
│ └── route.ts ← Presentation層(API)
└── features/
└── futsal/
├── application/
│ ├── IRequestParticipationApplicationService.ts
│ └── RequestParticipationApplicationService.ts
└── domain/
└── recruitment/
└── RecruitmentEntity.ts※ APIの配置はフレームワークによって異なります。この例では、Next.jsのRoute HandlerをPresentation層として扱っています。