【Flutter】小規模〜中規模開発におけるベストプラクティス
はじめに
Flutterでアプリを開発する際、プロジェクト立ち上げ時のアーキテクチャ設計が、その後の開発効率や保守性を大きく左右します。
この記事では、小規模から中規模のFlutterプロジェクトにおける、実践的なベストプラクティスを3つのポイントに絞って解説します。
1. MVVM + Repositoryパターンの採用
基本構造
View (UI層)
↓
ViewModel (状態管理)
↓
Repository (データアクセス)
↓
API Client
メリット
- テストが容易: 各レイヤーを独立してテスト可能
- 保守性が高い: 変更の影響範囲が限定される
- 再利用性: コンポーネントを他の画面でも活用できる
ディレクトリ構成例
lib/
├── model/ # データモデル
├── api/ # APIクライアント
├── repository/ # Repository層
├── page/ # 画面UI
│ └── user_list_page/
│ ├── user_list_page.dart
│ └── component/
│ ├── user_list_viewmodel.dart
│ └── user_list_state.dart
└── provider/ # Riverpod Provider
2. Riverpod + Hooks + Freezedの技術スタック
各パッケージの役割
Riverpod: 状態管理とDI(依存性注入)
Flutter Hooks: ライフサイクル管理を簡潔に
Freezed: イミュータブルなデータクラスを自動生成
実装例
// Modelの定義 (Freezed)
@freezed
class User with _$User {
const factory User({
required int id,
required String name,
required String email,
}) = _User;
}
// Stateの定義
@freezed
class UserListState with _$UserListState {
const factory UserListState({
@Default([]) List<User> users,
@Default(false) bool isLoading,
}) = _UserListState;
}
// ViewModelの実装
class UserListViewModel extends StateNotifier<UserListState> {
UserListViewModel(this._repository)
: super(const UserListState());
Future<void> fetchUsers() async {
state = state.copyWith(isLoading: true);
final users = await _repository.fetchUsers();
state = state.copyWith(users: users, isLoading: false);
}
}
メリット
- 型安全性: コンパイル時にエラーを検出
- 開発効率: ボイラープレートコードを自動生成
- テスト容易性: モックを使ったテストが簡単
3. プロジェクト新規立ち上げのチェックリスト
初期設定
# fvmでFlutterバージョン固定
fvm use 3.29.0 --force
# プロジェクト作成
fvm flutter create . \
--project-name my_app \
--platforms android,ios \
--org com.example \
-e
必須パッケージ
dependencies:
hooks_riverpod: ^2.4.0
flutter_hooks: ^0.20.0
freezed_annotation: ^2.4.0
dio: ^5.0.0
retrofit: ^4.0.0
go_router: ^13.0.0
dev_dependencies:
build_runner: ^2.4.0
freezed: ^2.4.0
json_serializable: ^6.7.0
設計の基本原則
- Single Source of Truth: 状態は一箇所でのみ管理
- 単方向データフロー: データの流れを一方向に保つ
- Immutableプログラミング: 不変なデータクラスを使用
- 関心の分離: UI/ビジネス/データアクセスを明確に分離
まとめ
Flutter開発で成功するためには、以下の3つがポイントです:
- MVVM + Repositoryで明確なレイヤー分離
- Riverpod + Hooks + Freezedで型安全かつ効率的な開発
- プロジェクト初期から適切な構造で始める
これらのベストプラクティスを採用することで、保守性が高く、スケーラブルなアプリケーションを構築できます。
詳細な実装例やコード例は、フルバージョンの記事をご覧ください:
この記事が、Flutterアプリ開発の参考になれば幸いです!
