Riverpodを使用したFlutterアプリケーションにおけるリポジトリ層の設計
Flutterアプリケーションの開発において、状態管理は非常に重要な要素です。Riverpodは、Flutterの状態管理において柔軟性とテストのしやすさを提供するライブラリの一つです。この記事では、Riverpodを使用した際のリポジトリ層の設計に焦点を当て、特にrefの扱い方について解説します。
間違いのあるコード例
リポジトリ層でProviderRefを直接使用することは、以下のようなコードで見られる一般的な間違いです。
final videoInfoRepositoryProvider = Provider<VideoInfoRepository>((ref) {
return VideoInfoRepository(ref);
});
class VideoInfoRepository {
final ProviderRef ref;
VideoInfoRepository(this.ref);
Future<List<VideoInfo>> fetchYoutubeVideos() async {
final apiClient = ref.read(youtubeApiClientProvider);
return apiClient.fetchYoutubeItems();
}
}
このコードでは、VideoInfoRepositoryがProviderRefを直接受け取り、それを使用して他のプロバイダー(この場合はyoutubeApiClientProvider)から値を読み取っています。このアプローチは、リポジトリの再利用性とテストのしやすさを低下させます。
正解のコード例
リポジトリ層でのrefの扱い方を改善するには、依存性をコンストラクタ経由で注入する方法が推奨されます。以下は、改善されたコード例です。
final videoInfoRepositoryProvider = Provider<VideoInfoRepository>((ref) {
final youtubeApiClient = ref.read(youtubeApiClientProvider);
return VideoInfoRepository(youtubeApiClient);
});
class VideoInfoRepository {
final YoutubeApiClient youtubeApiClient;
VideoInfoRepository(this.youtubeApiClient);
Future<List<VideoInfo>> fetchYoutubeVideos() async {
return youtubeApiClient.fetchYoutubeItems();
}
}
このコードでは、VideoInfoRepositoryのコンストラクタにYoutubeApiClientを直接渡しています。これにより、リポジトリはProviderRefに依存しなくなり、その結果、リポジトリのテストが容易になり、再利用性が向上します。
リポジトリ層でrefを直接扱わない理由
テストのしやすさ: リポジトリがProviderRefに依存しないことで、モックやダミーのデータソースを簡単に注入でき、テストが容易になります。
再利用性の向上: ProviderRefに依存しないことで、リポジトリを他のFlutterアプリケーションや、Riverpodを使用していない環境でも再利用しやすくなります。
責務の分離: リポジトリ層はデータの取得に集中し、状態管理の詳細から分離されるべきです。依存性の注入を通じて、この原則を守ることができます。
refの適切な使用場所
プロバイダーの作成時: 他のプロバイダーから値を読み取る必要がある場合にref.readやref.watchを使用します。
StateNotifierやChangeNotifier内: 外部の状態やサービスにアクセスするためにrefを使用します。
Discussion