Clean ArchitectureのInputPortとOutputPortの引数には必ずDTOを使おう
Kotlin使ってるからコンテナクラス(DTO)なんていらんでしょ!ってサボってたら、思わぬところで罠にかかったので供養します。
Clean Architecture
InputPortとOutputPortの二つはそれぞれControllerまたはPresenterに実装します。
当然ですが、複数のUseCaseを一つのクラスに実装する場合もあります。
同じメソッド名に潜む罠
複数のUseCaseを一つのクラスで実装する場合、実装したメソッドがどのUseCaseに対応するのか特定できる状態である必要があります。
UseCaseごとにメソッド名を変えてしまっても良いですが、同じメソッド名(execute(), handle()など)で統一し、オーバーロードによって解決することがほとんどだと思います。
その場合、書き方によってはUseCaseによっては一つのクラスに引数が完全に一致するメソッドを複数実装しなければならず、オーバーロードによる識別が不可能になります。
解決策
UseCaseごとにユニークなメソッド名、または引数にする必要があります。
メソッド名を統一する選択を行なった場合は、UseCaseの引数の代わりとしてUseCase名に基づいたコンテナクラスを作ってあげると良いでしょう。
例
data class HogeUseCaseInputPortInput(val hoge: String)
interface HogeUseCaseInputPort {
fun execute(input: HogeUseCaseInputPortInput)
}
data class HogeUseCaseOutputPortInput(val hoge: String)
interface HogeUseCaseOutputPort {
fun execute(input: HogeUseCaseInputPortInput)
}
~~コンテナクラスの名前がダサいのは置いといて、~~このようなUseCaseを徹底すれば引数が被ってオーバーロードできなくなるという問題はなくなります。いくら同じクラスに大量のUseCaseを実装使用が全て一意にユースケースを特定できます。
まとめ
ユースケースとコンテナクラスはセットで作りましょう。
作らないと後々地獄を見ます。私は見ました。