Flutter × Clean Architectureを現場や個人で使用していて、Abstractを時々拝見します。
意味を理解し今後もうまく活用できればと思いまとめました。
下記のような観点で基本的な理解を深めたいかたは、ぜひご覧ください。
目次
この記事でわかること
- Abstractの基本・基礎的な理解
- Abstractの簡単な使用方法(Clean Architecture)
Abstractとは
Abstractとは、Dartにおいて、「インスタンス化できないクラス」を定義するためのキーワードです。
- 使用する目的:
- クラス設計上、「共通のインターフェース(型)」として扱うため
- 特徴:
- メソッドの実装を省略できる(中身のない関数定義だけ)
- インスタンス化できない
- implements や extends で具体クラスに引き継がれて実装される
使用する3つのモチベーション
- 依存の整理
- UI層・ドメイン層がインフラ層(Firebaseなど)に依存しない構造にする
- テスト容易性
- 実装を差し替えてテスト用のモックに置き換えやすくする
- スケーラビリティ
- 実装を簡単に切り替えられるようにして将来の変更に強くする
Abstractの使用例
シチュエーション
- Flutter × Clean Architecture
- FirebaseのAuthを監視する
- RiverpodのProviderで管理する
Abstractを今回使う理由
- Data層とPresentation層を繋ぐため(疎結合にする)
- 別のDB(例: supabase)に切り替えても汎用できるようにするため
Data層のFirebaseのAuth情報取得
- 実際の取得関数をData層で管理(authStateChanges)
- implementsを使用してAuthRepository(Abstractを使用した抽象クラス)を使用
// FirebaseのAuthの状態を取得
class FirebaseAuthRepositoryImpl implements AuthRepository {
@override
Stream<User?> authStateChanges() {
return FirebaseAuth.instance.authStateChanges();
}
}
今回の中継役となる抽象クラス
Abstractを使用しData層とPresentation層の中継をする
// FirebaseAuthのData層とPresentation層の間のインターフェース
abstract class AuthRepository {
Stream<User?> authStateChanges();
}
Presentation層で使用するProvider
UIに渡すためのProvider(Riverpodを使用)
// 中継役を型としたProvider
final authRepositoryProvider = Provider<AuthRepository>((ref) {
return FirebaseAuthRepositoryImpl();
});
// 実際のxx_page.dartから呼ぶ出すためのStreamProvider(上記Providerを使用)
final authStateProvider = StreamProvider<User?>((ref) {
return ref.watch(authRepositoryProvider).authStateChanges();
});
まとめ:Abstractを使うメリット
- 実装に依存せずUI側のコードを書ける(柔軟性アップ)
- テストのためにMockに差し替え可能(テスト性アップ)
- Clean Architecture的な設計と相性が良い(保守性アップ)
最後に
Abstractを使用することで下記のようなメリットあります。
- テストが容易に
- 依存関係が整理しやすく
- 別のサービスに展開する汎用性が上がる
ただ個人開発などの小さいアプリでは不要かもですが、実務や汎用性を高めたいアプリ開発においては、必要かもで理解しとくと便利かなと思います。
ではまた。
コメント