Flutter Dart Code ReviewSAFE
The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.
Overview
The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.
bd656e3e97c4OBSERVED · 2026-09-20What it tells the agent
The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.
---
name: flutter-dart-code-review
description: ウィジェットのベストプラクティス、状態管理パターン(BLoC、Riverpod、Provider、GetX、MobX、Signals)、Dartのイディオム、パフォーマンス、アクセシビリティ、セキュリティ、クリーンアーキテクチャをカバーするライブラリに依存しないFlutter/Dartのコードレビューチェックリスト。
origin: ECC
---
# Flutter/Dartコードレビューベストプラクティス
Flutter/Dartアプリケーションをレビューするための包括的なライブラリに依存しないチェックリスト。これらの原則は、どの状態管理ソリューション、ルーティングライブラリ、またはDIフレームワークを使用していても適用されます。
---
## 1. 全般的なプロジェクトの健全性
- [ ] プロジェクトは一貫したフォルダー構造に従っている(フィーチャーファーストまたはレイヤーファースト)
- [ ] 適切な関心の分離: UI、ビジネスロジック、データレイヤー
- [ ] ウィジェットにビジネスロジックがない; ウィジェットは純粋にプレゼンテーション
- [ ] `pubspec.yaml`が整理されている — 未使用の依存関係がなく、バージョンが適切に固定されている
- [ ] `analysis_options.yaml`に厳格なリントセットと厳格なアナライザー設定が含まれている
- [ ] 本番コードに`print()`文がない — `dart:developer`の`log()`またはロギングパッケージを使用
- [ ] 生成されたファイル(`.g.dart`、`.freezed.dart`、`.gr.dart`)が最新か`.gitignore`に含まれている
- [ ] プラットフォーム固有のコードが抽象化の背後に分離されている
---
## 2. Dart言語の落とし穴
- [ ] **暗黙的なdynamic**: 型アノテーションの欠如が`dynamic`につながる — `strict-casts`、`strict-inference`、`strict-raw-types`を有効にする
- [ ] **Null安全の誤用**: 適切なnullチェックやDart 3のパターンマッチング(`if (value case var v?)`)の代わりに過度な`!`(bang演算子)
- [ ] **型プロモーションの失敗**: ローカル変数プロモーションが機能する場所で`this.field`を使用
- [ ] **過度に広い例外のキャッチ**: `on`句なしの`catch (e)`; 常に例外型を指定する
- [ ] **`Error`のキャッチ**: `Error`のサブタイプはバグを示し、キャッチすべきでない
- [ ] **未使用の`async`**: `await`しない`async`マークされた関数 — 不要なオーバーヘッド
- [ ] **`late`の過剰使用**: nullable型やコンストラクターの初期化がより安全な場所での`late`の使用; エラーをランタイムに先送りにする
- [ ] **ループでの文字列連結**: 繰り返しの文字列構築には`+`の代わりに`StringBuffer`を使用
- [ ] **`const`コンテキストでの可変状態**: `const`コンストラクタークラスのフィールドは可変であるべきでない
- [ ] **`Future`の戻り値の無視**: 意図を示すために`await`を使用するか明示的に`unawaited()`を呼び出す
- [ ] **`final`が使える場所での`var`**: ローカル変数には`final`を、コンパイル時定数には`const`を優先
- [ ] **相対インポート**: 一貫性のために`package:`インポートを使用
- [ ] **公開された可変コレクション**: パブリックAPIは生の`List`/`Map`ではなく変更不可能なビューを返すべき
- [ ] **Dart 3パターンマッチングの欠如**: 冗長な`is`チェックと手動キャストの代わりにswitch式と`if-case`を優先
- [ ] **複数の戻り値のための使い捨てクラス**: 単一使用のDTOの代わりにDart 3のレコード`(String, int)`を使用
- [ ] **本番コードでの`print()`**: `dart:developer`の`log()`またはプロジェクトのロギングパッケージを使用; `print()`はログレベルがなくフィルタリングできない
---
## 3. ウィジェットのベストプラクティス
### ウィジェットの分解:
- [ ] `build()`メソッドが約80-100行を超える単一ウィジェットがない
- [ ] ウィジェットがカプセル化と変化の仕方(再構築の境界)によって分割されている
- [ ] ウィジェットを返すプライベートな`_build*()`ヘルパーメソッドが別のウィジェットクラスに抽出されている(要素の再利用、const伝播、フレームワーク最適化を可能にする)
- [ ] 可変のローカル状態が必要でない場合、Statelessウィジェットが優先される
- [ ] 抽出されたウィジェットが再利用可能な場合、別のファイルに存在する
### Constの使用:
- [ ] `const`コンストラクターを可能な限り使用 — 不要な再構築を防ぐ
- [ ] 変化しないコレクションに`const`リテラルを使用(`const []`、`const {}`)
- [ ] すべてのフィールドがfinalの場合、コンストラクターが`const`として宣言されている
### Keyの使用:
- [ ] 並べ替え時に状態を保持するために`ValueKey`をリスト/グリッドで使用
- [ ] `GlobalKey`は控えめに使用 — ツリー全体の状態アクセスが本当に必要な場合のみ
- [ ] `UniqueKey`を`build()`内で使用しない — フレームごとに再構築を強制する
- [ ] 単一の値ではなくデータオブジェクトのアイデンティティに基づく場合は`ObjectKey`を使用
### テーマとデザインシステム:
- [ ] 色は`Theme.of(context).colorScheme`から取得 — `Colors.red`やhex値のハードコードなし
- [ ] テキストスタイルは`Theme.of(context).textTheme`から取得 — 生のフォントサイズのインライン`TextStyle`なし
- [ ] ダークモードの互換性を確認 — 明るい背景についての仮定なし
- [ ] スペーシングとサイジングは一貫したデザイントークンまたは定数を使用し、マジックナンバーではない
### buildメソッドの複雑さ:
- [ ] `build()`内にネットワーク呼び出し、ファイルI/O、または重い計算がない
- [ ] `build()`内に`Future.then()`または`async`作業がない
- [ ] `build()`内にサブスクリプション作成(`.listen()`)がない
- [ ] `setState()`が可能な限り小さいサブツリーに限定されている
---
## 4. 状態管理(ライブラリに依存しない)
これらの原則はすべてのFlutter状態管理ソリューション(BLoC、Riverpod、Provider、GetX、MobX、Signals、ValueNotifier など)に適用されます。
### アーキテクチャ:
- [ ] ビジネスロジックがウィジェットレイヤーの外にある — 状態管理コンポーネント(BLoC、Notifier、Controller、Store、ViewModelなど)内
- [ ] 状態マネージャーが依存関係をインジェクションで受け取り、内部で構築しない
- [ ] サービスまたはリポジトリレイヤーがデータソースを抽象化 — ウィジェットと状態マネージャーはAPIやデータベースを直接呼び出すべきでない
- [ ] 状態マネージャーが単一の責務を持つ — 無関係な懸念を処理する「god」マネージャーなし
- [ ] コンポーネント間の依存関係がソリューションの規約に従う:
- **Riverpod**では: プロバイダーが`ref.watch`を通じて他のプロバイダーに依存することは予期されている — 循環または過度に絡み合ったチェーンのみフラグを立てる
- **BLoC**では: BLoCが他のBLoCに直接依存すべきでない — 共有リポジトリまたはプレゼンテーション層の調整を優先する
- 他のソリューションでは: コンポーネント間通信の文書化された規約に従う
### イミュータビリティと値の等値性(イミュータブル状態ソリューション用: BLoC、Riverpod、Redux):
- [ ] 状態オブジェクトがイミュータブル — インプレースで変異させるのではなく、`copyWith()`またはコンストラクターで新しいインスタンスを作成
- [ ] 状態クラスが`==`と`hashCode`を適切に実装(すべてのフィールドが比較に含まれる)
- [ ] メカニズムがプロジェクト全体で一貫 — 手動オーバーライド、`Equatable`、`freezed`、Dartレコード、またはその他
- [ ] 状態オブジェクト内のコレクションが生の可変`List`/`Map`として公開されていない
### リアクティビティの規律(リアクティブ変異ソリューション用: MobX、GetX、Signals):
- [ ] 状態がソリューションのリアクティブAPI(MobXでの`@action`、signalでの`.value`、GetXでの`.obs`)を通じてのみ変異される — 直接フィールド変異は変更追跡をバイパスする
- [ ] 派生値がソリューションの計算メカニズムを使用し、冗長に保存されない
- [ ] リアクションとディスポーザーが適切にクリーンアップされる(MobXでの`ReactionDisposer`、Signalsでのeffectクリーンアップ)
### 状態の形状設計:
- [ ] 相互に排他的な状態がsealed型、ユニオン変体、またはソリューションの組み込み非同期状態型(例: Riverpodの`AsyncValue`)を使用 — ブールフラグ(`isLoading`、`isError`、`hasData`)は使わない
- [ ] すべての非同期操作がローディング、成功、エラーを異なる状態としてモデル化
- [ ] すべての状態変体がUIで網羅的に処理 — サイレントに無視されるケースなし
- [ ] エラー状態が表示のためのエラー情報を持つ; ローディング状態は古いデータを持たない
- [ ] 可変のデータがローディングインジケーターとして使用されない — 状態は明示的
```dart
// 悪い例 — ブールフラグの混乱が不可能な状態を許可する
class UserState {
bool isLoading = false;
bool hasError = false; // isLoading && hasErrorが表現可能!
User? user;
}
// 良い例(イミュータブルアプローチ) — sealed型が不可能な状態を表現不可能にする
sealed class UserState {}
class UserInitial extends UserState {}
class UserLoading extends UserState {}
class UserLoaded extends UserState {
final User user;
const UserLoaded(this.user);
}
class UserError extends UserState {
final String message;
const UserError(this.message);
}
// 良い例(リアクティブアプローチ) — observableのenum + データ、リアクティビティAPIを通じた変異
// enum UserStatus { initial, loading, loaded, error }
// ソリューションのobservable/signalを使用してstatusとdataを別々にラップする
```
### 再構築の最適化:
- [ ] 状態コンシューマーウィジェット(Builder、Consumer、Observer、Obx、Watchなど)をできるだけ狭くスコープする
- [ ] 特定のフィールドが変化した場合のみ再構築するためにセレクターを使用 — すべての状態エミッションで再構築しない
- [ ] ツリーを通じた再構築の伝播を止めるために`const`ウィジェットを使用
- [ ] 計算/派生状態がリアクティブに計算され、冗長に保存されない
### サブスクリプションと廃棄:
- [ ] すべての手動サブスクリプション(`.listen()`)が`dispose()` / `close()`でキャンセルされる
- [ ] ストリームコントローラーが不要になったら閉じられる
- [ ] タイマーが廃棄ライフサイクルでキャンセルされる
- [ ] フレームワーク管理のライフサイクルが手動サブスクリプションより優先される(`.listen()`よりも宣言的ビルダー)
- [ ] 非同期コールバックでの`setState`前に`mounted`チェック
- [ ] `await`後に`BuildContext`を`context.mounted`をチェックせずに使用しない(Flutter 3.7+) — 古いコンテキストはクラッシュを引き起こTrust audit
SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | NA |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | PASS |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- none-observed
- Network
- none-observed
- Shell
- none-observed
- Dependencies
- pinned
- Secrets in source
- none-found
Findings (0)
No findings outside the package's declared scope.
Gates applied: no_behavioural_pass.
bd656e3e97c4full audit observations/trust-audit/skill/affaan-m__flutter-dart-code-review.json · Report an issue / request a re-scanAudit history
Every audit this skill has had.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-09-20 | bd656e3e97c4 | SAFE | B | 89 | first audit |
Questions
What does the Flutter Dart Code Review skill do?
The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.
Is Flutter Dart Code Review safe to install?
The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.
What can Flutter Dart Code Review access on my machine?
The audit observed no filesystem, network or shell use at all in its source.
How current is this page?
The grade is for one exact copy of the source (bd656e3e97c4), read on 2026-09-20. The repository is watched, and a new audit runs when it changes — this is the first audit.