MSAにおけるUseCaseのインターフェース設計:なぜリクエストをCommandに変換するのか?**
1. はじめに
マイクロサービスアーキテクチャ(MSA)において、UseCaseのインターフェース(インバウンドポート)を設計する際に、
「コントローラーから受け取ったリクエストをそのまま渡さずに、Commandオブジェクトに変換して渡す」 という設計パターンがよく使われます。
2. なぜCommandオブジェクトに変換するのか?
✅ 1. UseCase(ビジネスロジック)とWebリクエストのモデルを分離するため
- コントローラーが受け取る
Request DTO
は、HTTPリクエストの仕様に依存しています。 - しかし、UseCaseはHTTPリクエストの形式に依存してはいけません。
- そこで、ビジネスロジックが理解しやすいCommandオブジェクトに変換して渡すことで、ユースケースの独立性を保ちます。
✅ 2. 不必要な依存関係をなくすため
-
Request DTO
には、Spring MVC などの Webフレームワークに依存した情報 が含まれることがあります。 -
UseCase
のインターフェースでこれを直接扱うと、アプリケーションのアーキテクチャがWebフレームワークに強く依存してしまう ため、拡張性が低下します。 - Commandオブジェクトを使用することで、ユースケースがフレームワークに依存しないクリーンな設計 になります。
✅ 3. 入力データの責務を明確にするため
-
RegisterMembershipCommand
のような 明確なオブジェクトを定義することで、必要なデータのみを扱う ことができます。 - 例えば、リクエストには
timestamp
やIPアドレス
など不要なデータが含まれることがありますが、Commandには ユースケースに必要なデータだけを渡せます。
3. コードで理解する
Controller
@RestController
@RequestMapping("/membership")
@RequiredArgsConstructor
public class MembershipController {
private final RegisterMembershipUseCase registerMembershipUseCase;
@PostMapping("/register")
public ResponseEntity<Void> register(@RequestBody RegisterMembershipRequest request) {
// 🔹 Request DTO → Commandオブジェクトに変換
RegisterMembershipCommand command = new RegisterMembershipCommand(request.getUsername(), request.getEmail());
// 🔹 ユースケースを実行(Requestをそのまま渡さない)
registerMembershipUseCase.registerMembership(command);
return ResponseEntity.ok().build();
}
}
ポイント:
-
RegisterMembershipRequest
はWebリクエストのDTO(データ転送オブジェクト) -
RegisterMembershipCommand
はビジネスロジック用のCommandオブジェクト - コントローラーは
Request → Command
に変換してからユースケースに渡す
UseCase Interface
public interface RegisterMembershipUseCase {
void registerMembership(RegisterMembershipCommand command);
}
ポイント:
- UseCaseはWebのリクエスト形式に依存しない
- Commandオブジェクトを受け取ることで、どのアダプター(Web、CLI、gRPCなど)からも再利用できる
Commandオブジェクト
@Getter
@AllArgsConstructor
public class RegisterMembershipCommand {
private final String username;
private final String email;
}
ポイント:
- Commandオブジェクトは 純粋なデータ構造 であり、Webのリクエストとは関係ない
- ユースケースに 必要な情報だけを持たせる
4. まとめ
✅ UseCaseはWebリクエストのDTOに依存しないようにするべき
✅ Commandオブジェクトを使うことで、ユースケースを独立した形で設計できる
✅ フレームワーク依存を避け、アプリケーションの再利用性・保守性を向上させる