Claude Code を使った Flutter UI イテレーション:実践ワークフロー
Claude Code を使った Flutter UI イテレーション:ユーザーストーリーをウィジェットツリー、状態、ナビゲーションに変換しつつ、変更をモジュール化してレビューしやすく保つ実践的ループ。

問題:速い UI イテレーションが混乱に変わらないようにする
速い Flutter UI 作業は最初はうまくいきます。レイアウトを微調整し、ボタンを追加し、フィールドを移動すると画面はすぐに良くなります。問題は数回のラウンドの後に現れます。スピードが大量の変更になり、誰もレビューしたがらない差分が積み上がるのです。
チームがよく陥る失敗は次の通りです:
- ウィジェットツリーが計画なしに成長し、"小さな"変更が多くのファイル編集を強いる。
- 状態が UI コードにベタ付けされ、リビルドが予測困難になりバグの追跡が難しくなる。
- ナビゲーションロジックが散らばり(ここで push、あそこでは pop)、実際のユーザーの動きとフローが一致しなくなる。
- 名前付けがぶれ、コンポーネントが重複し、どのウィジェットが“本物”かわからなくなる。
- Diff が巨大になり、レビュアーは上っ面しか見ず、問題が見逃され、後でリグレッションが出る。
大きな原因の一つは「ワンビッグプロンプト」アプローチです:機能全体を説明して画面のフルセットを一度に要求し、大きな出力を受け入れてしまう。アシスタントは助けようとしますが、コードの多くの部分に触れてしまい、変更が混乱し、レビューやマージがリスクになるのです。
反復可能なループは、明確さを強制し、インパクト範囲を限定することでこれを防ぎます。"機能を作る"のではなく、次を繰り返します:1 件のユーザーストーリーを選び、それを証明する最小の UI スライスを生成し、そのスライスに必要な最小限の状態だけを追加し、1 つのパスのナビゲーションだけを配線する。各パスはレビューしやすい小ささに保たれ、ミスは簡単に元に戻せます。
ここでの目標は、ユーザーストーリーを具体的な画面、状態処理、ナビゲーションフローに変換する実践的なワークフローを示すことです。うまくやれば、モジュラーな UI パーツ、小さな差分、要件変更時の驚きが少ないコードベースが残ります。
ユーザーストーリーを作れる UI スペックに変える
ユーザーストーリーは人間向けに書かれており、ウィジェットツリー向けではありません。何かを生成する前に、ストーリーを「見える挙動」を記述した小さな UI スペックに変換してください。"Done" はテスト可能であるべきです:ユーザーが見て、タップして、確認できること。デザインが "モダンに感じる" かどうかは DONE の基準ではありません。
スコープを具体的に保つ簡単な方法は、ストーリーを 4 つのバケットに分けることです:
- Screens:何が変わり、何がそのままか。
- Components:どの新しい UI 部品が現れ、どこに置かれるか。
- States:loading、success、error、empty、それぞれが何を表示するか。
- Events:タップ、スワイプ、プルトゥリフレッシュ、戻る、リトライ。
ストーリーがまだ曖昧なら、次の問いに平易な言葉で答えてください:
- どの画面が変わり、どの画面がそのままか?
- どの新しいコンポーネントが現れ、どこに属するか?
- どんな状態が存在し、それぞれ何を表示するか?
- どのイベントが状態を変えるか?
- アプリを動かしたあと 30 秒でできる受け入れチェックは何か?
制約は早めに追加してください。制約はすべてのレイアウト選択を導きます:テーマの基本(色、間隔、タイポグラフィ)、レスポンシブ(まずは縦向きの電話、その後タブレット幅)、アクセシビリティ最小限(タップターゲットサイズ、読みやすいテキストスケーリング、アイコンの意味のあるラベル)など。
最後に、何が安定で何が柔軟かを決めて、コードベースを無駄に回転させないようにします。安定しているものは他の機能が依存するもの(ルート名、データモデル、既存 API)です。柔軟なものはレイアウト構造やマイクロコピー、正確なウィジェット構成などで、反復しても比較的安全です。
例:"ユーザーとして、詳細画面からアイテムをお気に入りに保存できる"。ビルド可能な UI スペックの一例:
- 詳細画面にブックマークアイコンを表示する。
- タップで保存状態をトグルする。
- 保存中は小さなプログレスインジケータを表示する。
- 失敗時はインラインエラーを表示し、リトライのアクションを提供する。
- ナビゲーションはそのまま(新しいルートは不要)。
これだけで作成、レビュー、反復ができ、推測が不要になります。
反復ループを設定して差分を小さく保つ
小さな差分は遅く作業することではありません。各 UI 変更がレビューしやすく、元に戻しやすく、壊しにくくするためのものです。最も単純なルール:1 回の反復で 1 画面か 1 つのインタラクションだけを扱うこと。
始める前に狭いスライスを選んでください。"Orders 画面に空状態を追加する"は良いスライスです。"Orders フロー全体を作り直す"は不適切です。チームメイトが 1 分で理解できる差分を目標にしてください。
安定したフォルダー構造も変更を囲い込むのに役立ちます。シンプルで機能優先のレイアウトはウィジェットやルートをアプリ全体に散らすことを防ぎます:
lib/
features/
orders/
screens/
widgets/
state/
routes.dart
ウィジェットは小さく合成的に保ってください。ウィジェットが明確な入力と出力を持つと、状態に触れずにレイアウトを変えられ、UI を書き換えずに状態を変更できます。プレーンな値とコールバックを受け取るウィジェットを優先し、グローバル状態を避けてください。
レビュー可能なループの例:
- そのスライスについて 3~6 行の UI スペックを書く(何が現れるか、タップが何をするか、読み込み/エラーの見た目)。
- 必要最小限のファイルのみを生成または編集する(多くの場合は 1 画面と 1〜2 ウィジェット)。
- 画面を実行して、1 回のクリーンアップパス(名前付け、間隔、未使用 prop の削除)を行う。
- スライスに合ったメッセージでコミットする。
厳格なルールを設けてください:すべての変更は元に戻しやすく、分離しやすいこと。作業中に横道のリファクタを避けてください。関連しない問題に気づいたら、書き留めて別のコミットで修正します。
ツールがスナップショットとロールバックをサポートするなら、各スライスをスナップショットポイントとして使ってください。Koder.ai のようなプラットフォームはスナップショットとロールバックを含み、思い切った UI 変更を試す際に安全性を高めます。
さらに、初期の反復を穏やかに保つ習慣:共有コンポーネントを編集するより新しいウィジェットを追加することを優先してください。共有コンポーネントは小さな変更が大きな差分に変わる箇所です。
ステップバイステップ:ユーザーストーリーからウィジェットツリーを生成する
速い UI 作業が安全であるのは、考えることとタイプすることを分けるときです。まずコード生成の前に明確なウィジェットツリープランを作ってください。
-
ウィジェットツリーのアウトラインだけを依頼します。ウィジェット名、階層、各部分が何を表示するかが欲しいだけです。まだコードは書かないでください。ここで欠けている状態や空の画面、変なレイアウト選択を安価に見つけられます。
-
コンポーネントの責任分解を依頼します。各ウィジェットは集中させます:あるウィジェットはヘッダー、別はリスト、別は空/エラー UI を担当する、といった具合です。後で状態が必要ならその旨をメモしておきますが、今は実装しません。
-
画面のスキャフォールドとステートレスウィジェットを生成します。まずはプレースホルダコンテンツと明確な TODO を含む単一の画面ファイルから始めます。入力は明示的に(コンストラクタパラメータ)しておき、後で実際の状態を差し替えられるようにします。
-
スタイリングとレイアウトの詳細は別パスにします:間隔、タイポグラフィ、テーマ、レスポンシブ動作。スタイリングは別差分にしてレビューを単純に保ちます。
有効なプロンプトパターン
アシスタントが実装不能な UI を想像しないように、制約を前提に置いてください:
- 対象デバイス(電話のみ、タブレットも、向き)
- デザイン制約(Material 3、既存テーマ色、間隔ルール)
- ナビゲーション期待(戻る挙動、deep link があれば)
- 受け入れ基準(何が表示されタップ可能であるべきか)
- 既存コードの境界(どのファイル/ウィジェットを残すか、命名規則)
具体例:ユーザーストーリーが "As a user, I can review my saved items and remove one." の場合、アプリバー、アイテム行のあるリスト、空状態を含むウィジェットツリーを依頼します。次に SavedItemsScreen、SavedItemTile、EmptySavedItems のような分解を要求します。まずステートレスなスキャフォールドとダミーデータで始め、最後にスタイリング(区切り線、パディング、明確な削除ボタン)を別パスで追加します。
UI コードを膨らませずに状態処理を追加する
イテレーションが崩れるのは、ウィジェットごとに決定ロジックが入り始めたときです。ウィジェットツリーはダムに保ち、状態を読み取って描画するだけにします。
まず状態を平易な言葉で命名してください。ほとんどの機能は単に "loading" と "done" 以上が必要です:
- Loading(初回読み込みやリフレッシュ)
- Empty(まだデータがない)
- Error(リクエスト失敗、権限拒否)
- Success(データ準備完了)
- Partial input(フォームが開始されているが有効でない状態)
次に状態を変えるイベントを列挙します:タップ、フォーム送信、プルトゥリフレッシュ、戻る、リトライ、ユーザーがフィールドを編集した、など。事前にこれをやっておくと後の推測が減ります。
ウィジェットから状態を分離する
機能ごとに 1 つの状態アプローチを選んで貫いてください。目標は "ベストなパターン" ではなく、差分が一貫することです。
小さな画面では、ChangeNotifier や ValueNotifier のようなシンプルなコントローラで十分なことが多いです。ロジックは 1 箇所にまとめます:
- 入力:UI からのイベント(submit、refresh、edit)
- 出力:UI が描画する単一の状態オブジェクト
- 副作用:API 呼び出しやナビゲーション要求
コードを書く前に、状態遷移を平易な英語(あるいはチームが使う言語)で書いてください。ログイン画面の例:
"ユーザーが Sign in をタップしたら:Loading にする。メールが無効なら Partial input に留めてインラインメッセージを表示。パスワードが間違っていれば Error をセットしてリトライを有効化。成功したら Success にして Home に遷移。"
それに合致する最小限の Dart コードを生成してください。レビューは差分とルールを比較するだけで済みます。
無効な入力に対するテスト可能なルールを追加する
バリデーションを明示化します。無効な入力時にどうするか決めてください:
- 送信をブロックするのか、送信を許可してエラーを表示するのか?
- どのフィールドがどのタイミングでエラーを表示するか?
- 戻ると途中入力を破棄するか保持するか?
これらを文章化しておけば、UI はクリーンに保てて状態コードも小さくできます。
実際のユーザー挙動に合うナビゲーションを設計する
良いナビゲーションは小さな地図として始めます。各ユーザーストーリーについて、次の 4 つの瞬間を書き出してください:ユーザーがどこから入ってくるか、次に最もありそうなステップ、どうやってキャンセルするか、"戻る" が何を意味するか(前の画面か安全なホームか)。
まずルートマップを作り、次に画面間で何を渡すかをロックする
シンプルなルートマップは、後で手戻りを生む質問に答えます:
- Entry:どの画面が最初に開き、どこから(タブ、通知、deep link)来るか
- Next:主要な前進パス
- Cancel:中断したときにどこに着地するか
- Back:戻ることが許されているか、何を保持するか
- Fallback:必要なデータが足りないときにどこに飛ばすか
次に画面間で渡すパラメータを定義します。明示的にしてください:IDs(productId、orderId)、フィルタ(期間、ステータス)、ドラフトデータ(部分入力のフォーム)。これを省くと、コンテキストを見つけるためにグローバルシングルトンに詰め込むか、画面を再構築する羽目になります。
Deep link と結果を返すパターンに備える
Deep link は当日に出荷しなくても重要です。ユーザーがフローの途中に着地したときにどうするか決めておく:欠損データを読み込めるか、安全な入り口にリダイレクトするか。
また、どの画面が結果を返すかを決めてください。例:"住所選択"画面は addressId を返し、チェックアウト画面はフルリフレッシュせずに更新する。返す形は小さく型付きにしておくと差分が読みやすくなります。
実装前にエッジケースを列挙してください:未保存の変更(確認ダイアログを表示)、認証が必要(ログイン後に再開)、データが欠けている/削除されている(エラー表示と明確な脱出経路)。
UI 変更をレビューしやすくモジュール化する
速く反復するときの本当のリスクは "UI が間違っている" ことではなく "レビューできない UI" です。チームメイトが何が変わったのか、なぜ変わったのか、何が安定しているのかがわからなければ、次の反復はどんどん遅くなります。
役立つルール:まずインターフェース(API)を固定し、それから内部を動かす。公開ウィジェットの props(入力)、小さな UI モデル、ルート引数を安定化させてください。これらが名前付きで型付きなら、ウィジェットツリーを大きく変えても他の部分を壊しません。
差分を小さく保つための小さな安定した縫い目を優先する
コード生成前に差分フレンドリーな計画を出すように依頼してください。どのファイルが変わり、どれを untouched にするかを示す計画が欲しいです。これでレビューが集中し、意図せぬリファクタによる振る舞い変更を防げます。
差分を小さく保つパターン:
- 公開ウィジェットは薄く保つ:必要なデータとコールバックだけを受け取る。
- ビジネスルールは早めにウィジェットの外に出す:コントローラ/ビューモデルに移す。
- UI が頻繁に変わらなくなったら、明確で型付きの API を持つ再利用可能ウィジェットに抽出する。
- ルート引数は明示的に(多くの optional フィールドより単一の引数オブジェクト)。
- PR の説明に短い変更ログを入れる:何を変えたか、なぜ、何をテストするか。
レビュアーが好む具体例
ユーザーストーリーが "チェックアウトから配送先住所を編集できる" の場合、まずルート引数を固定します:CheckoutArgs(cartId, shippingAddressId) は安定させます。次に画面内部を反復します。レイアウトが落ち着いたら AddressForm、AddressSummary、SaveBar に分割します。
状態処理が変わっても(たとえばバリデーションがウィジェットから CheckoutController に移るなど)、レビューは読みやすいままです:UI ファイルは主に描画に関する変更だけで、コントローラにロジックの差分がまとまって見えます。
AI アシスタントと反復する際の一般的な失敗と罠
反復を遅くする最速の方法は、アシスタントに「すべてを一度に」変更させることです。1 つのコミットがレイアウト、状態、ナビゲーションを同時に変えると、レビュアーは何が原因で壊れたのかわからず、ロールバックが面倒になります。
安全な習慣は、1 反復=1 意図です:ウィジェットツリーを整え、その後で状態を配線し、最後にナビゲーションを接続します。
混沌を生む間違い
生成されたコードが画面ごとに新しいパターンを発明するのを許すのは問題です。1 ページは Provider を使い、次は setState、3 番目はカスタムコントローラを持つようになると、アプリはすぐに一貫性を失います。小さなパターンセットを選び、それを守ってください。
別の問題は build() 内に非同期処理を置くことです。クイックデモでは動いても、リビルド時に複数回呼ばれ、チラつきや追跡困難なバグを招きます。呼び出しは initState()、ビューモデル、あるいは専用コントローラに移し、build() は描画に集中させてください。
命名は静かな罠です。コンパイルは通るが Widget1、data2、temp のような名前だと将来のリファクタが苦労します。明確な名前はアシスタントが次の変更をより良く生成するのにも役立ちます。
回避ガードレール:
- 1 回の反復で変更するのは「レイアウト」「状態」「ナビゲーション」のうち 1 つだけ
- 機能内で同じ状態パターンを使う
build()内にネットワークや DB 呼び出しを置かない- プレースホルダの名前は機能を増やす前に変更する
- ネストが増える代わりにウィジェットを抽出する
ネスト地獄の罠
視覚的なバグ修正で Container、Padding、Align、SizedBox をどんどん重ねると、ツリーは読みにくくなります。ボタンの位置がおかしいときは、ラッパーを増やすのではなく、まずラッパーを減らす、単一の親レイアウトを使う、あるいは制約を持つ小さなウィジェットに抽出することを試してください。
例:読み込み時に合計金額がジャンプするチェックアウト画面。アシスタントは価格行を "安定化" するためにさらに多くのウィジェットでラップするかもしれません。よりクリーンな修正は、行構造を変えずに単純な読み込みプレースホルダでスペースを確保することです。
次のコミット前のクイックチェックリスト
コミット前に 2 分のパスでユーザー価値と意図しないリグレッションから保護してください。目的は完全性ではなく、この反復がレビューしやすく、テストしやすく、元に戻しやすいことを保証することです。
コミット準備チェックリスト
ユーザーストーリーを一度読み、実行中のアプリ(あるいは簡単なウィジェットテスト)に対して次を検証します:
- ウィジェットツリーがストーリーと一致するか: 受け入れ基準の主要要素が存在し、可視であるか。テキスト、ボタン、空白が意図的に見えるか。
- すべての状態に到達できるか: Loading、Error、Empty がコード上のスケッチで終わらず、各状態をトリガーできて見栄えが受け入れられるか。
- ナビゲーションと戻る挙動は妥当か: 戻るが期待する画面に戻り、ダイアログが閉じ、deep link(使う場合)は妥当な場所に着地するか。
- 差分は小さく所有されているか: 変更が責務の明確な少数ファイルに限定されているか。ドライブバイリファクタはないか。
- ロールバックがきれいか: これを revert しても他の画面がビルド・実行できるか。一時フラグやプレースホルダ資産を残していないか。
簡単な現実チェック:新しい Order details 画面を追加したなら、(1) 一覧から開ける、(2) ローディングスピナーが見える、(3) エラーをシミュレートできる、(4) 空の注文を見ることができる、(5) 戻るで一覧に戻れる——という最低限の動作ができるべきです。
ワークフローがスナップショットやロールバックをサポートするなら、大きなレイアウト変更前にスナップショットを取り、メインブランチを危険にさらさないでください。Koder.ai のようなプラットフォームはこれをサポートします。
現実的な例:ユーザーストーリーから 3 回の反復で画面まで
ユーザーストーリー:"As a shopper, I can browse items, open a details page, save an item to favorites, and later view my favorites."。言葉から画面までを 3 つの小さなレビュー可能なステップで進めます。
反復 1: ブラウズリスト画面のみに集中します。実データに結びつかないレンダリングができる程度のウィジェットツリーを作る:Scaffold、AppBar、プレースホルダ行の ListView、読み込みと空状態の明確な UI。状態はシンプルに:loading(CircularProgressIndicator)、empty(短いメッセージと場合によっては Try again ボタン)、ready(リストを表示)。
反復 2: 詳細画面とナビゲーションを追加します。onTap がルートを push し、小さなパラメータオブジェクト(例:item id、title)を渡すことを明示します。詳細ページはまず読み取り専用で、タイトル、説明プレースホルダ、Favorite アクションボタンを持ちます。ポイントはストーリーに合わせること:list -> details -> back、余計なフローはなし。
反復 3: お気に入りの状態更新と UI フィードバックを導入します。お気に入りの単一の真実(メモリ内でも可)を追加し、両画面に配線します。タップでアイコンを即時更新し小さな確認(SnackBar など)を表示。次に同じ状態を読む Favorites 画面を追加し、空状態を処理します。
レビュー可能な差分の例:
browse_list_screen.dart:ウィジェットツリー+loading/empty/ready UIitem_details_screen.dart:UI レイアウトとナビゲーションパラメータ受け取りfavorites_store.dart:最小限の状態ホルダと更新メソッドapp_routes.dart:ルートと型付きナビゲーションヘルパーfavorites_screen.dart:状態を読み空/リスト UI を表示
もし 1 つのファイルが "すべてが起こる場所" になったら、次に進む前に分割してください。小さく名前のわかるファイルは次の反復を速く安全にします。
次のステップ:このループを機能全体で繰り返せるようにする
ワークフローが "集中しているときだけ機能する" のでは困ります。画面を切り替えたり、別のメンバーが触ったら壊れます。ループを習慣にするには書き留め、変更サイズにガードレールを設けてください。
再利用できるプロンプトテンプレートを作る
チームで同じテンプレートを使えば、すべての反復が同じ入力から始まり同じ種類の出力を生みます。短く具体的に:
- ユーザーストーリー+受け入れ基準(Done の定義)
- UI 制約(デザインシステム、間隔、再利用すべきコンポーネント)
- 状態ルール(状態はどこに置くか、ローカルか共有か)
- ナビゲーションルール(ルート、deep link、戻る挙動)
- 出力ルール(触るファイル、更新すべきテスト、差分で説明すること)
これによりアシスタントが途中で新しいパターンを思いつく確率が下がります。
差分の "小ささ" を定義して予測可能にする
レビューで守りやすい小ささの定義を決めてください。例:各反復で変更ファイル数を制限し、UI リファクタと振る舞い変更を分ける。
シンプルなルール例:
- 反復ごとに変更は 3〜5 ファイル以内
- 1 反復につき 1 つの新しいウィジェットか 1 つのナビゲーションステップ
- 反復途中で新しい状態管理手法を導入しない
- 次の反復に行く前に変更はコンパイルして動作確認をする
悪いステップをすばやく取り消せるようチェックポイントを設けてください。最低でもコミットやローカルスナップショットを使い、大きなリファクタ前に保存します。スナップショット/ロールバックをサポートするなら積極的に使ってください。
エンドに:チャットベースで Flutter アプリを生成・修正できるワークフローを探しているなら、Koder.ai のようなツールは計画モードで生成前にプランと想定ファイル変更をレビューできる機能を提供します。
よくある質問
Flutter の UI イテレーションをレビューしやすいサイズに保つには?
小さくてテスト可能な UI スペック を最初に作成してください。3~6 行で次をカバーします:
- 表示されるもの(主要ウィジェット/コンポーネント)
- タップの挙動(主要なインタラクション)
- 読み込み/エラー/空状態の見た目
- 30秒で検証する方法
そのスライス(たいていは 1 画面 + 1〜2 ウィジェット)のみを実装します。
ユーザーストーリーをビルド可能な UI スペックにする最良の方法は?
ユーザーストーリーを次の 4 つに分けて書き換えます:
- 画面(Screens):何が変わるか、何がそのままか
- コンポーネント(Components):新しいウィジェットと配置場所
- 状態(States):loading、empty、error、success(それぞれ何を表示するか)
- イベント(Events):タップ、戻る、リトライ、リフレッシュ、フォーム編集
受け入れ条件をすぐに説明できないなら、そのストーリーはまだ曖昧で、クリーンな差分には向きません。
AI アシスタントにまず何を頼むべきですか:コード、それとも構造?
まず ウィジェットツリーのアウトラインのみを生成するように頼みます(名前+階層+各部分が何を表示するか)。コードはまだ求めません。
次に コンポーネントの責務分解(どのウィジェットが何を担当するか)を要求します。
その後に、明示的な入力(値+コールバック)を持つ ステートレスなスキャフォールド を生成し、スタイリングは別パスにします。
「一度に大きく頼む(one big prompt)」アプローチはなぜ汚い差分を生みやすいのか?
反復ごとに 1 つの意図だけ を扱うというルールを適用してください。
- 反復 A:ウィジェットツリー/レイアウト
- 反復 B:状態の接続
- 反復 C:ナビゲーションの接続
一つのコミットでレイアウト、状態、ルートすべてを変えると、レビュアーは何が原因でバグが出たかわかりづらくなり、ロールバックが大変になります。
状態を追加してもウィジェットコードを肥大化させないには?
ウィジェットを“ダム(無垢)”に保ち、状態をレンダリングするだけにします。実用的なデフォルト:
- 1 つのコントローラ/ビューモデルがイベントと非同期処理を担当
- 単一の状態オブジェクト(loading/empty/error/success)を UI に公開
- UI は状態を読み、コールバック(retry、submit、toggle)を呼ぶ
build() に非同期呼び出しを置かないでください。リビルドごとに複数回走る原因になります。
ほとんどの画面で計画すべき UI 状態は何ですか?
実装前に画面で想定される状態を言葉で整理してください。一般的なパターン:
- Loading: スピナーやスケルトンを表示
- Empty: メッセージ+アクション(例:Retry)
- Error: インラインエラー+Retry
- Success: コンテンツを描画
そして、それらの間を移動させるイベント(refresh、retry、submit、edit)を列挙します。コードは書かれたルールと比較しやすくなります。
ナビゲーションフローが散らばって一貫性を失うのを防ぐには?
ストーリーごとに小さなフローマップを書いてください:
- Entry(入り口):どこから来るか(タブ、通知、deep link)
- Next(次):主要な前進パス
- Cancel(キャンセル):中断したらどこに行くか
- Back(戻る):戻るは前の画面か、セーフなホームか
- Fallback(フォールバック):必須データがない場合の遷移
画面間で渡すパラメータ(productId、orderId、フィルタ、ドラフト)を明確にしておくと、グローバルに状態を詰め込む悪習を避けられます。
UI 変更を囲い込むのに適したフォルダー構成は?
機能ごとのフォルダー構成をデフォルトにすると変更が分散しません。例:
lib/features/<feature>/screens/lib/features/<feature>/widgets/lib/features/<feature>/state/lib/features/<feature>/routes.dart
各反復は、1 つの機能フォルダーにフォーカスし、余計なドライブバイリファクタを避けてください。
過剰設計せずに Flutter UI をモジュール化するには?
インターフェース(公開 API)を安定させ、内部は自由に動かしてください。ルール:
- 公開ウィジェットの prop は小さく型を明確に
- 値+コールバックを渡すことを優先し、グローバル状態への直接参照を避ける
- ルート引数は明示的に(単一の args オブジェクトが良い)
- 同じ箇所を何度も変えなくなったら抽出して再利用する
レビュアーは、レイアウトが動いても入力/出力が安定していることを重視します。
安全な UI 反復のための簡単な事前コミットチェックリストは?
2 分ほどで次をチェックしてください:
- 読み込み/空/エラー/成功 の各状態はトリガーして見られるか
- 戻る が期待通りに動くか(不自然なジャンプはないか)
- 変更は責務が明確な少数のファイルに限定されているか
- 一時フラグやプレースホルダが残っていないか
ワークフローがスナップショットやロールバックをサポートするなら、レイアウト大改修前にスナップショットを取っておくと安全です。