Clean Architectureでは、ポート(Port)という概念が重要な役割を果たします。ポートは、システムの内部と外部の境界を定義するインターフェースです。外部の要素(たとえば、データベースやUI)はポートを介して内部のビジネスロジックとやり取りします。
ポートの役割は、内部と外部の依存関係を逆転させることにあります。具体的には、内部のビジネスロジックは具体的な実装に依存せず、抽象的なポートを介して外部の要素とやり取りします。これにより、内部のビジネスロジックは独立してテストや変更が可能になります。
ポートは、一般的にインターフェース(Interface)や抽象クラス(Abstract Class)として実装されます。具体的な実装は、ポートを実装するアダプタ(Adapter)として作成されます。アダプタは、ポートと具体的な要素(たとえば、データベースアクセスクラスやUIライブラリ)との橋渡しを行います。
以下に、ポートの実装例を示します。
// ポートのインターフェース
public interface UserRepository {
User getUserById(String userId);
void saveUser(User user);
}
// ポートの実装クラス(アダプタ)
public class DatabaseUserRepository implements UserRepository {
public User getUserById(String userId) {
// データベースからユーザーを取得する処理
}
public void saveUser(User user) {
// データベースにユーザーを保存する処理
}
}
// ビジネスロジックのクラス(ポートを使用)
public class UserService {
private UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void createUser(String userId, String name) {
User user = new User(userId, name);
userRepository.saveUser(user);
}
}
上記の例では、UserRepository
がポートのインターフェースであり、DatabaseUserRepository
がその具体的な実装です。UserService
はビジネスロジックのクラスであり、コンストラクタの引数としてUserRepository
を受け取ります。
このようにして、ビジネスロジックは具体的なデータベースアクセスクラスに依存せず、抽象的なポートを介してデータベースとやり取りします。これにより、ビジネスロジックのテストはポートのモックを使用して行うことができます。
Clean Architectureのポートの概念を理解し、適切に活用することで、システムの柔軟性と保守性を向上させることができます。