Application Service interface
DDDでの位置づけ
Application Serviceのinterfaceは、DDDで必ず作るものではありません。
このガイドラインでは、APIが何を呼び出せるか、何を渡し、何が返るかを、実装を読まなくても分かるようにするため、interfaceを作ります。
interfaceで決めること
interfaceには、呼び出せるメソッド、そのメソッドへ渡す情報、処理後に返す結果を定義します。処理の内容は書きません。
参加申請では、IRequestParticipationApplicationServiceを呼び出し口にします。
コードで表す
// IRequestParticipationApplicationService.ts
// execute()に渡す参加申請の情報
export type RequestParticipationInput = {
recruitmentId: string; // 参加したい募集のID
participantId: string; // 参加を申請する人のID
now: Date; // 参加を申請した日時
};
// 参加申請ユースケースの呼び出し口
export interface IRequestParticipationApplicationService {
// 参加申請を実行する
execute(input: RequestParticipationInput): Promise<void>;
}execute()へ渡す情報はRequestParticipationInputで決めています。返却値はPromise<void>なので、この例では処理結果のデータを返しません。
Application Serviceが実装する
RequestParticipationApplicationServiceは、IRequestParticipationApplicationServiceで決めたexecute()を実装します。
import type {
RequestParticipationInput,
IRequestParticipationApplicationService,
} from "./IRequestParticipationApplicationService";
export class RequestParticipationApplicationService
implements IRequestParticipationApplicationService {
async execute(input: RequestParticipationInput): Promise<void> {
// 参加申請ユースケースの処理
}
}interfaceを通して呼び出す
APIは、実装クラスではなくIRequestParticipationApplicationServiceを受け取り、execute()を呼び出します。
// APIがinterfaceとしてApplication Serviceを受け取る
async function handleRequest(
applicationService: IRequestParticipationApplicationService,
): Promise<void> {
await applicationService.execute({
recruitmentId,
participantId: signedInUser.id,
now: new Date(),
});
}APIは、参加申請がどのクラスで実装されているかを意識せず、interfaceで決めた呼び出し方だけを使います。
ディレクトリで表す
src/features/futsal/
└── application/
├── IRequestParticipationApplicationService.ts ← interface
└── RequestParticipationApplicationService.ts ← 実装このガイドラインでは、interfaceの先頭にIを付けます。実装クラスにはIを付けず、ファイル名だけで役割を見分けられるようにします。