Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AI時代だからこそ「Bloc」を採用する価値があるのかもしれない

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

 AI時代だからこそ「Bloc」を採用する価値があるのかもしれない

Avatar for takuro abe

takuro abe

May 17, 2026

Other Decks in Programming

Transcript

  1. 自己紹介 02 名前 takuro abe 所属 クラスメソッド株式会社 リテールアプリ共創部 最近の趣味 ランニング

    5/10(日) 鹿沼さつきマラソン 10km 走ってきました 🏃 LINKS DevelopersIO / abe-tk X / @abe_tk6
  2. 目次 03 Agenda 01 AI時代の開発 02 BLoCパターン 03 Flutter Bloc

    04 Flutter Bloc が AI開発で効く理由 05 まとめ
  3. AI時代の開発について 05 AI・SKILL・TEAM AI時代の開発を、 3つの視点で整理します。 01 / AI AIエージェントが コードを書く時代

    AIエージェントが、実装の主戦力になっている。 02 / SKILL SKILL・ルール・ワークフローで 品質が安定する エージェントの「振る舞い」を整備すれば、出力 のブレが大きく減る。 03 / TEAM チーム共有で 全員が同じ品質に SKILL をチームで共有すれば、誰が書いても近い 品質のコードが出てくる。
  4. BLoCパターン — 定義 08 Definition BLoC = Business Logic Component。

    Business Logic Component UI からビジネスロジックを切り離し、再利用可能なコンポーネントとして扱うデザインパターン。 DartConf 2018 で提唱。 BLoC design guidelines — BLoC の 4 原則 ・ 入出力はすべて Stream / Sink ・ 依存は注入可能でプラットフォーム非依存 ・ BLoC 内にプラットフォーム分岐を書かない ・ 上記を守れば実装は自由 UI design guidelines — UI 側の 4 原則 ・ 「十分に複雑」なコンポーネントには 対応する BLoC を 1 つ ・ コンポーネントは入力を「そのまま」BLoC に流す ・ 出力も可能な限り「そのまま」表示する ・ 分岐は BLoC が出す真偽値で行う 出典: Flutter / AngularDart – Code sharing, better together (DartConf 2018)
  5. BLoCパターン — 分離の価値 09 TEST・REUSE・CHANGE なぜビジネスロジックを 分離する のか。 01 /

    TEST UI なしで ロジックを検証できる BLoC 単体でユニットテストが書ける。Stream の入出力で状態遷移も追える。 02 / REUSE UI から独立、 横断で使い回せる 画面差し替えでもロジックは流用できる。プラッ トフォーム横断の再利用が元々の動機。 03 / CHANGE 責務が分かれ、 変更に強い UI / ロジック / データの責務が分かれるので、片 方の変更が他方を壊しにくい。差分レビューも局 所化する。
  6. Flutter Bloc の構造 11 Structure — UI ⇄ Bloc ⇄

    Data 状態の変更は Bloc が一手に 引き受ける。 UI 画面を描画する。 ユーザー操作を Event と して送出 する。 Bloc 状態変更の唯一点。 Event を受けて State を 発行する。 Data API・DB などの外部リソ ース。 Bloc からの呼び出しに応 える。 ※ Cubit(Event の代わりに公開メソッド呼び出しで State を更新する簡易版)には触れない。 UI Bloc Data Event State request response
  7. Flutter Bloc の状態管理 — Event / State / Bloc 12

    State management Event / State / Bloc。 flutter_bloc で3つを定義していくのが基本。 Event 入力 UIで何が起きたかを表す。 命名は 過去形、 sealed class で網羅。 sealed class HogeEvent {} final class HogeFugaPressed extends HogeEvent {} final class HogePiyoPressed extends HogeEvent {} State 出力 現在の状態を表す。 典型は loading / success / failure。 enum HogeStatus { initial, loading, success, failure } final class HogeState { const HogeState({ this.status = HogeStatus.initial, this.hoges = const <Hoge>[], this.exception, }); final HogeStatus status; final List<Hoge> hoges; final Exception? exception; // ※ 実運用は Equatable / freezed で == を実装 } Bloc 変換 Event を受け取って State を 発行 する。 on<Event> にハンドラを登録するだけ。 final class HogeBloc extends Bloc<HogeEvent, HogeState> { HogeBloc({required this.repository}) : super(const HogeSt on<HogeFugaPressed>((event, emit) async { // ... }); on<HogePiyoPressed>((event, emit) async { // ... }); } final HogeRepository repository; }
  8. Flutter Bloc のテスト — AAA(Arrange-Act-Assert)パターン 13 Test Bloc の単体テストは bloc_test

    で AAA に沿って書ける。 Arrange 準備 テスト対象と周辺を 組み立てる。 Stub・初期状態の設定。 blocTest<HogeBloc, HogeState>( '...', setUp: () { when(() => repo.fetchHoges()) .thenAnswer((_) async => hoges); }, build: () => HogeBloc(repository: repo), seed: () => const HogeState(status: HogeStatus.loading), // ... ); Act 実行 検証したい操作を 1つ実行。 Event を add するだけ。 blocTest<HogeBloc, HogeState>( '...', // ... act: (bloc) => bloc.add(HogeFugaPressed()), // ... ); Assert 検証 State 遷移と副作用を 検証。 順序も含めて検査できる。 blocTest<HogeBloc, HogeState>( '...', // ... expect: () => [ isA<HogeState>() .having((s) => s.status, 'status', HogeStatus.loadi isA<HogeState>() .having((s) => s.status, 'status', HogeStatus.succe ], verify: (_) { // 副作用検証 (mock の呼ばれ回数など) }, );
  9. ポイント 15 Point Flutter Bloc は 実装の ガードレール になる。 FRAMEWORK

    構造を 強制する FOR AI AGENTS AI にも 扱いやすい
  10. 具体例1 — 一方向フロー → 誤用が物理的に起きない 16 Example 01 / 03

    状態の書き換えは、 Bloc 内の emit() だけ。 FRAMEWORK CONSTRAINT // UI からは Event を投げることしかできない context.read<HogeBloc>().add(HogeFugaPressed()); // state setter は存在しないので、そもそもコンパイルが通らない context.read<HogeBloc>().state = const HogeState(...); // ← compile error // emit() は Bloc 内のハンドラからしか呼べない final class HogeBloc extends Bloc<HogeEvent, HogeState> { HogeBloc() : super(const HogeState()) { on<HogeFugaPressed>((event, emit) { emit(const HogeState(status: HogeStatus.loading)); }); } } EFFECT 誤用が 物理的に起きない 「UI で state を直接いじる」がそもそも書けない。 AI レビューが パターンマッチ になる フローから外れた実装は、構造を見るだけで即わかる。 チームで書いても ブレない 「正しさ」がフレームワーク側に守られている。
  11. 具体例2 — Event/State/Bloc の役割 → AI 雛形が一発で決まる 17 Example 02

    / 03 Event 名を1つ渡すだけで、 雛形が ほぼ確定する。 PROMPT HogeFugaPressed を追加してください。 GENERATED FILES lib/feature/hoge/ ├── bloc/ │ ├── hoge_event.dart ← HogeFugaPressed を追加 │ ├── hoge_state.dart (既存利用) │ └── hoge_bloc.dart ← on<HogeFugaPressed> └── data/ └── hoge_repository.dart (既存利用) test/feature/hoge/bloc/ └── hoge_bloc_test.dart ← blocTest 追加 OUTPUT EVENT Event クラス 過去形 / sealed class。 HogeFugaPressed がそのまま型になる。 BLOC Bloc ハンドラ on<HogeFugaPressed> 登録 + Repository 呼び出し。 STATE State 遷移 HogeStatus enum で loading → success / failure を表現。 TEST blocTest(AAA パターン) Arrange / Act / Assert が build / act / expect にそのまま対応。
  12. 具体例3 — レイヤー分離 → テストの組み方が決まる 18 Example 03 / 03

    レイヤー分離が テスト手法の選択に そのまま対応する。 レイヤー テスト手法 モック対象 備考 Data test() API クライアント / DB 外部 I/O をモック化、純粋な変換に集中 Bloc blocTest() Repository AAA パターンが自然に強制される UI testWidgets() Bloc(MockBloc) UI は状態を描画するだけ、と割り切れる EFFECT 何をモックすべきか 自明 レイヤーが分かれているので、隣のレイヤーだけをモッ クすればいい。 テストが 独立する UI / Bloc / Data を、それぞれ単独で検証できる。 AI でも 迷わない レイヤーごとの書き方が決まっているので、生成しても 安定する。
  13. アプローチ — AI 開発で Flutter Bloc の構造を活かす 19 Approach ここまでの構造は、

    SKILL / agent でチームに展開できる。 SAMPLE REPO — github.com/abe-tk/github-issues-app-with-bloc .claude/ ├─ skills/ │ ├─ bloc/ ← flutter_bloc の作法 │ ├─ layered-architecture/ ← レイヤー分離ルール │ ├─ testing/ ← bloc_test の使い方 │ ├─ plan-and-review/ ← 計画 → AI レビュー │ └─ impl-and-review/ ← 実装 → AI レビュー ├─ agents/ │ ├─ architecture-reviewer ← レイヤー違反を検知 │ ├─ plan-reviewer ← 実装計画の妥当性 │ ├─ standards-reviewer ← 命名・コーディング規約 │ └─ test-reviewer ← テスト観点 └─ rules/flutter.md ← Flutter 共通ルール ABSORBED BY AI + SKILL 冗長さ・学習コストはAIとSKILLが吸収する ボイラープレートは AI、学習コストは SKILL に埋め込める。 REVIEWER AGENTS 構造から外れた実装を自動検知 レビュワーエージェントが、一方向フローからの逸脱を即座に指摘する。 TEAM REPRODUCIBILITY 構造の明確さ = SKILL化のしやすさ 迷いポイントが少ないからこそ、ルール化・共有が機能する。
  14. まとめ 21 BLOC・AI・SKILL AIが書く時代、 Flutter Bloc の ガードレール は武器になる。 01

    / BLOC Flutter Bloc は 書き方のガードレールになる Event / State / Bloc + レイヤー分離で、実装の自 由度を構造的に絞る。 02 / AI AI が書いても 同じ形に収まる 誤用が物理的に起きず、雛形は一発で決まる。レ ビューもパターンマッチで済む。 03 / SKILL 冗長さは AI と SKILL が吸収する ボイラープレートは AI、学習コストは SKILL に埋 め込める。冗長さは AI 時代の差にならない。