Repository

RepositoryとはEntityの永続化を隠蔽するためのモジュールです。

なぜRepositoryが必要なのか?

Repositoryを使用することで、ビジネスロジックを記述する際に、どのDBを使っていて、どのような問い合わせを行ってデータを取得したり、保存するのかを意識する必要がなくなります。

また、DBの種類を変更する際に、ビジネスロジックを変更する必要がなくなります。。

Repositoryが役に立った実例

Flutterを用いたモバイルアプリ開発の際に、当初はFirestoreのSDKを用いてクライアントから直接Firestoreに問い合わせを行っていました。

しかし、セキュリティー的にクライアントから直接Firestoreに問い合わせを行ってはいけないことが分かり、Cloud Functionsを経由してFirestoreにアクセスする必要がでてきました。

データアクセスはRepositoryで行うようにしていたため、Repositoryを書き換えるだけで、ビジネスロジックを変更する必要がなく、開発を進めることが可能となりました。

Repositoryの実装例

Dart言語では、次のようなインターフェースでRepositoryを定義することが多いです。 save, delete, findByIdなどは、どのDBでも同じインターフェースで定義することができるため、ビジネスロジックを記述する際に、どのDBを使用しているのかを意識する必要がなくなります。

abstract class UserRepository {
  Future<User?> findById(UserId id);
  Future<User?> findByEmail(String email);
  Future<User> save(User user);
  Future<void> delete(UserId id);
}

RepositoryはEntityが存在してるということを意識せずに、ビジネスロジックを記述できたほうがよいため、基本的にはcreate, updateなどを個別に定義することはしないです。

アンチパターン

Repositoryにビジネスロジックを記述することは避けるべきです。

たとえば、ユーザーのログイン日時を更新する際に、以下のようなメソッドをRepositoryに定義するようなことは避けるべきです。

abstract class UserRepository {
  Future<User?> updateLastLoginAt(UserId id);
}

ログイン日時の更新は、永続化とは無関係の操作であるため、saveメソッドを利用して、repo.save(user.updateLatestLoginAt())のようにビジネスロジック側で計算して、永続化を行うことが推奨されます。