変化に強いアプリのための再生成優先開発
再生成優先の開発手法を学び、パッチではなくクリーンなコードを再生成してデータ・ロジック・UIを柔軟に更新する方法を紹介します。

なぜパッチ的な変更が技術的負債になるのか
パッチとは、新しい要件が出たときに最小限の編集でねじ込むことです。速く感じられるのは事実ですが、問題は各パッチが局所的な修正でしかなく、局所的な修正はアプリのあるべき構造と一致しないことが多い点です。
時間が経つとパッチが積み重なります。アプリは動き続けますが、コードや設定が食い違い始めます:データベースはあることを示し、UIは別のことを示し、実際のルールは三箇所に分散して存在する──その不一致が技術的負債です。それは単なる「悪いコード」ではありません。次の変更を行うコストが増大している状態です。
見分け方は大抵こうです:
- ロジックが絡まり、小さなルール変更で多くの画面やエンドポイントに手を入れないといけない。
- フィールドが重複する("status"、"ticket_status"、"status_v2"など)。名前を変えるのが怖くなるためです。
- UIが壊れやすくなり、特定のデータ形状やエッジケースに依存する。
- 回避策が「一時的」フラグになり、永久に残る。
- 修正に追随する修正が必要になり、他に何が壊れるかわからない。
リスクが急速に増えるのが特に辛い点です。本来小さな変更のはずのこと(承認ステップの追加、価格ルールの調整、ユーザーロールの分割など)が、どの程度影響が出るか予測できずリスクの高いリリースになります。テストは勘に頼るものになり、ロールバックは難しくなります。
再生成優先開発はまさにこれへの対策です。目的は、変更が予測可能で可逆的になり、プラットフォームが昨日のハックを引き継がずにクリーンなコードを再生成できるようにアプリを構造化することです。
実践的な目標:
- データの明確な真実の源を一つにする(ほぼ同じ意味の重複フィールドをなくす)。
- ルールはUIやエンドポイントに散らさず、一箇所にまとめる。
- UIは表示と入力に専念し、ビジネス判断に関与させない。
- 変更はモデルやロジックで行い、出力を手作業で編集するのではなく再生成する。
AppMasterのようなプラットフォームはこれをサポートします。アプリはモデルとビジュアルロジックで定義され、プラットフォームがフルソースコードを再生成します。ただし、再生成をクリーンに保つには、そもそもパッチ駆動の構造を避ける必要があります。
再生成優先開発が意味すること
再生成優先開発は、アプリを手作業で編集されたコードの塊ではなく、明確なモデル群として扱います。モデルを変更して再生成すれば、新しく一貫したバージョンのアプリが得られます。重要なのは、次の変更を難しくする余計なハックを残さずに変更を出荷することです。
パッチ優先のワークフローでは、小さな要求(新しいステータスフィールド、承認ステップの追加など)は最も早く収まる場所に直ちに追加されます。誰かがAPIハンドラを少し変え、ある画面を更新し、別の場所に特別なケースを加え──その結果、ロジックは散らばります。数サイクル後、誰もどこに本当のルールがあるか確信を持てなくなります。
再生成優先では、真実の源はモデルにあります:
- データモデル:エンティティ、フィールド、リレーション、制約
- ビジネスロジックモデル:何が起きるかを決めるルールとフロー
- UIモデル:画面、コンポーネント、データへのバインディング方法
これらのモデルから生成されるもの(APIエンドポイント、データベースアクセス、Web/モバイルコード)は出力であり、そこで素早い修正を行う場所ではありません。
AppMasterでは、バックエンドにGo、WebにVue3、モバイルにKotlinやSwiftUIなどを出力できます。要件が変わったらモデルを一度更新して再生成すれば、同じルールを複数ファイルから探す必要はありません。
これにより同じ定義が全レイヤーを駆動するので一貫性が保たれます。例えば「Ticket Status」が必須になれば、データベーススキーマ、バリデーション、API、UIバインディングが一緒に更新されるはずです。承認ルールが変われば、そのプロセスを更新すればすべてのエンドポイントと画面が同じロジックを反映します。
マインドセットの転換はシンプルです:意味のある箇所(モデル)を編集し、必要なものを生成する(コード)。
進化できるデータモデルを作る
再生成優先開発を機能させたいなら、最も変わるべきでない部分、つまりデータモデルから始めましょう。変更に強いアプリは、すべての画面が完璧だからではなく、コアエンティティが安定していて分かりやすい名前になっているから生き残ります。
まずは一年後も使われるであろう名詞から始めます。多くのアプリでは User、Account、Team、Ticket、Order、Invoice、Product、Message といったものです。これらが明確なら、ワークフロー、権限、UIの上に堅牢な基盤ができます。
命名は小さな詳細ではありません。後の変更が混乱したマイグレーションや壊れたロジックに変わるのを防ぎます。エンティティは単数形にし、フィールド名は一貫させ(created_at と createdAt のどちらかに統一)、現実に合った型を選んでください(通貨は decimal、タイムスタンプは合意したタイムゾーンルール)。小さな不一致がルール、フィルタ、レポートに広がります。
拡張を計画しつつ過剰設計は避けます。すべての将来フィールドを予測する必要はありませんが、よくある変更を安全にする設計は可能です:
- ステージごとにテーブルを増やすのではなく、新しい値を受け入れられるステータスフィールドを優先する。
- 常に存在しないデータはオプションフィールドにする(phone_number、external_idなど)。
- 監査用フィールド(created_at、updated_at、created_by)を早めに追加する。
- 実験的なデータはコアフィールドと分けて notes や metadata に置く。
ビジュアルなデータデザイナーがあると、コードになる前にリレーションや制約を可視化できます。AppMasterではData DesignerがスキーマをPostgreSQLにマップするため、テーブルやフィールド、リンクを一箇所でモデル化して要件が変わったときにクリーンなソースコードを再生成できます。
例:サポートポータルはTicketsをAccountsやUsersにリンクして始めます。後で優先度やカテゴリ、"Waiting on Customer" のような新しいステータスが要求されたとします。もしTicketsにすでにステータスフィールドと詳細用のオプションフィールドがあれば、値やフィールドを追加してもデータベースを再設計する必要はありません。再生成されたアプリはクエリとAPIの一貫性を保ち、ワンオフのパッチの山を避けられます。
目標は「今日読みやすく、明日に寛容であること」です。
ビジネスロジックをモジュール化し読みやすくする
ビジネスロジックは変更が壊れやすい箇所です。「今動く」ためのクイックフィックスがやがて特殊ケースの巣になり得ます。再生成優先開発では、ロジックを再生成しやすい形で設計し、誰かの頭の中にしか存在しないパッチに頼らないようにします。
実践的な方法は、各ワークフローを小さなブロックの集合として考えることです。各ブロックは1つの仕事だけを行います:入力を検証する、価格を計算する、経路を決定する、メッセージを送る、レコードを更新する。AppMasterではこれはBusiness Process Editorに自然に対応します。小さなプロセスは読みやすく、テストしやすく、再利用や差し替えもしやすくなります。
入力と出力を意識する
ブロックを作る前に二つを書き出してください:何が必要で、何を返すか。1文で説明できなければ、そのブロックは多くをやり過ぎています。
良いブロックは境界が明確です。明示的な入力(ユーザーロール、チケットステータス、注文合計)を受け取り、明示的な出力(承認/却下、最終価格、次のステップ)を返します。その明確さがあると、別のブロックに入れ替えても影響範囲を推測する必要がありません。
簡単なチェックリスト:
- ブロックは一つの目的だけ(検証、計算、ルーティングなど)
- 入力は外から渡す(どこかに「見つけに行く」ではない)
- 出力は返す(副作用に隠さない)
- 名前は結果を説明する(例:
ValidateRefundRequest) - エラーは一貫して扱う
隠れた依存を避ける
隠れた依存はロジックを脆弱にします。ワークフローがグローバルフラグや静かな状態変化、あるステップのどこかで設定される変数に依存していると、小さな編集で予期せぬ振る舞いが出ます。
状態は意図的にプロセスの中で渡してください。保存が必要なら明示的な場所(データベースフィールドなど)に保存し、明示的に読み出します。一つのステップでレコードを変更して別のステップがそれを察する、という「マジック」な振る舞いは避けましょう。
意思決定ポイントを見える化してください。例えばサポートポータルで "Is this ticket VIP?" や "Is it after business hours?" のような分岐が明確にラベル付けされていれば、将来「VIPルールが週末だけ変わった」という変更は素早く安全にできます。
ルールとデータからUIの関心事を分離する
変更に強いアプリは、UIを「ダム(単純)」に保てると再生成が容易です。画面は入力を集め、状態を表示し、ユーザーを案内するべきです。ビジネス判断がボタンやバリデーション、ワンオフの画面ロジックに隠れていると、次の要件ごとにパッチが増えます。
UIを共通のルールとデータの薄い層として扱いましょう。そうすればプレゼンテーションを再構築しても、決定ロジックを十箇所再実装する必要がなくなります。
UIが終わる場所、ビジネスルールが始まる場所
実用的な分割は:UIは明快さを扱い、ビジネスロジックは真実を扱う、です。UIはフォーマットやラベル付け、ユーザー補助を行い、ビジネスロジックが何が許可されるか、何が次に起きるかを決めます。
UIの責務の例:
- データの表示とユーザー入力の収集
- フォーマット(日付、通貨、電話マスク)
- 基本的な必須チェック(空かどうか)
- ロジックが返すエラーを平易な言葉で表示する
- ナビゲーションとレイアウト
ビジネスルールは画面外に置きます(例:ワークフローやプロセスエディタにて)。例:「返金にはマネージャーの承認が必要」「VIP顧客はキューをスキップ」「解決コードなしでチケットをクローズできない」などのルールは特定ページに結びつけず、データモデルと繋げておきます。
一度設計してWebとモバイルで再利用する
複数クライアント(Web とネイティブ)をサポートする場合、重複は乖離を生みます。共通パターン(チケットステータスバッジ、優先度セレクタ、顧客カード)には共通コンポーネントを再利用し、同じデータと同じルール結果を供給して挙動を一致させてください。
例えば、チケット状態をData Designerでモデル化し、状態変化を単一のビジネスプロセスで駆動し、Webとモバイルがそのプロセスを呼んで返された状態をレンダリングするようにすれば、"Escalated" が "Urgent review" に変わっても1箇所更新して再生成すれば済みます。
良いテストはこれです:もし画面を削除して明日作り直しても、アプリが同じルールを強制するなら分離は機能しています。
ステップバイステップ:クリーンな再生成のためにアプリを構造化する
再生成優先は、アプリを独立して変えられる明確な部分に分割すると最も効果的です。まずモジュールを考え、画面では考えないようにします。
コアモジュールの名前付けを行い、頭と作業の中で分離しておきます:データ(テーブルとリレーション)、プロセス(ロジック)、API(エンドポイント)、Web UI、Mobile UI。要件が変わったら、何を変えるべきで何を触らないべきかを指差せるべきです。
変更に強いままにするビルド順序
小さなループを使い、各ステップを控えめに保ちます:
- まずデータをモデル化する:実態に合ったエンティティ、フィールド、リレーション
- 再利用できるフローとしてビジネスプロセスを追加する。各プロセスは一つの仕事をする(Create Ticket、Assign Agent、Close Ticketなど)。
- ロジックが読みやすくなったらプロセスをAPIエンドポイントにつなぐ。エンドポイントはフローのラッパーとして扱い、ルールを隠す場にしない。
- UI画面はデータベーステーブルではなくユーザーのタスクに沿って構築する。
- 小さな変更ごとに再生成してテストする。
小さな例:ややこしいパッチを避けて変更する
サポートポータルをAppMasterで作っているとします。最初はTicketsとCommentsだけです。1週間後、Priority と "VIP顧客は常にHighで始まる" という新ルールが来ました。
モジュール構造なら、データモデルを変更して Priority を追加し、Create Ticket プロセスを更新して顧客タイプに基づいて Priority を設定し、再生成して主要なUIタスクが動くか確認するだけで済みます。複数の画面に散らばる修正は不要です。
小さな習慣が役立ちます:再生成ごとに主要フロー(作成、更新、権限チェック)を素早く実行してから次の機能を追加すること。
例:変わり続けるカスタマーサポートポータル
小さなサポートポータルを想像してください。顧客はログインして自分のチケット一覧を見て、詳細を開き、返信を追加します。サポート担当者は内部ノート付きで同じチケットを見ます。
再生成優先ではチケットのデータモデル、チケットの動かし方を定義するビジネスプロセス、そしてUI画面の三つを分離します。これらが明確なら、一方を変更しても他をパッチで補う必要がありません。
シンプルに始め、変化に備えて構造化する
最初のバージョンは最小限で構いません:
- データ:Users, Tickets, Messages
- プロセス:Create ticket, Reply, Assign to agent
- UI:Ticket list, Ticket details, New ticket form
AppMasterではこれがPostgreSQLバックエンドのデータモデル(Data Designer)、ルールのドラッグ&ドロップワークフロー(Business Process Editor)、別々のWeb/Mobile UIビルダーにきれいにマップされます。
変更1:優先度とSLA日付を追加
プロダクトがPriority(Low, Normal, High)とSLA期限日を求めてきたら、Ticketモデルにフィールドを追加し、作成プロセスでデフォルト優先度を設定し、エージェント画面でSLAを表示し、一覧画面にフィルタを加えます。プラットフォームがバックエンドとAPIを再生成するので、新しいフィールドはコード上で第一級になります。
変更2:クローズ前の承認ステップを追加
ある顧客ではチケットをクローズする前にマネージャー承認が必要になったとします。複数の画面にクローズルールを散らすのではなく、モデルに明確な状態(Open, Pending approval, Closed)を追加し、クローズプロセスを更新します:
- エージェントがクローズを要求
- システムが承認が必要かチェック
- マネージャーが承認または却下
- 承認後にのみチケットがクローズされる
ルールが1つのプロセスにあるため、UIは現在のステータスと次に許されるアクションを表示します。
変更3:モバイルのプッシュ通知
エージェントが返信したときにプッシュ通知が欲しい、という要望が出たとします。通知ロジックをUI側に埋め込まず、"New message" プロセスに通知モジュールをトリガーとして組み込みます。再生成すればネイティブアプリも更新され、手作業のパッチワークにはなりません。
再生成優先ワークフローを壊すよくあるミス
再生成優先はアプリが再生成可能なままでいるときにのみ機能します。チームが犯しがちなミスは今日 harmless に見えるクイックフィックスで、後に回避策を強いるようになります。
1) 生成されたコードを編集してしまう
生成された部分に手動編集を混ぜるのは、再生成性を失う最短ルートです。AppMasterのように実際のソースコードを生成するプラットフォームを使っているなら、ビジュアルプロジェクトを真実の源として扱ってください。再生成で再現できない変更は安全ではありません。
簡単なルール:視覚プロジェクトから再生成して変更を再現できないなら、それは安全な変更ではありません。
2) UIにルールを決めさせる
画面にビジネスルールをエンコードすると("このボタンはVIPユーザーにだけ表示"、"このフォームが合計をUIで計算する" など)、新しい画面ごとに特殊ケースが増えます。検証、権限、計算はビジネスロジック(Business Processなど)に置き、UIは結果を表示するだけにしましょう。
3) まだ使われないファンタジーなデータモデルを早期に作る
過剰モデリングは、使用実績がない段階で多くのフィールドやステータスを追加することです。変更のたびに多くの部分に手を入れる必要が出てきます。
知っていることから始め、小さなステップで拡張しましょう:
- 平易な言葉で説明できるフィールドだけを追加する。
- ステータス値は現実的に短く(3〜6程度)、20個も持たない。
- 巨大な1つのテーブルに意味を詰め込むより、必要なら後で新しいテーブルを追加する方を選ぶ。
4) 命名規約を飛ばす
命名が一貫しないとモデルやエンドポイントが混乱します:"Cust"、"Customer"、"Client" が混在するような状態です。再生成は機能しますが、人が変更時にミスをします。初期にシンプルなパターン(単数形のテーブル名、アクションの一貫した動詞)を決めて守りましょう。
5) 一つの巨大なワークフローを作る
最初は整然として見えても、一つの巨大なワークフローは後で変更が難しくなります。ロジックは小さなプロセスに分け、明確な入力と出力を持たせてください。サポートポータルなら "Create ticket"、"Assign agent"、"Send notification" を分けると、一部分を変えても他に影響を与えにくくなります。
再生成・出荷前の簡単チェック
再生成優先は安全に感じられるのは短いルーチンでよくある "静かな壊れ" を検出できるときだけです。再生成の前にアプリの構造に合わせた短い確認を行ってください:データ、ロジック、UI、API の順です。
高速チェックリスト:
- データ:エンティティとフィールドが現在の要件に合っているか、名前が一貫しているか、同義の二つのフィールドを持っていないか。
- ロジック:各ワークフローに明確な入力・出力・予測可能なエラーパスがあるか。
- UI:画面が共通コンポーネントを再利用し、ルールをハードコーディングしていないか。
- API:エンドポイントがワークフローに一貫してマッピングされているか。"このエンドポイントはどのワークフローに属するか?" と答えられるか。
- リリース:ランダムに "見た目で確認する" のではなく、小さく再現可能なテストスクリプトがあるか。
ルールの単一の真実の源を保ってください。例えばチケットの優先度が顧客のティアに依存するなら、それを一つのワークフローで定義し、APIとUIの両方がそれを反映するようにします。
10分程度のテストスクリプトで現実的な利用を模擬できます:
- 必須フィールドだけで新しいレコードを作成する。
- 主要ワークフローをトリガーして期待されるステータス変更を確認する。
- 既知のエラーケース(権限不足や必須データ欠如)を一つ試す。
- Webとモバイルの主要画面を開き、同じルールが同じように表示されるか確認する。
- 主要エンドポイントを1〜2呼び出し、UIが表示している内容と一致するか確認する。
何か失敗したら、まず構造(データ、ワークフロー、共有UI)を修正してから再生成してください。
次の一手:次の変更でこのアプローチを試す
まず改善する領域を一つ選び、範囲を小さく保ちます。最近の変更で手間がかかった箇所から始めましょう:データモデル、もつれたロジック、頻繁に "ちょっとだけ手直し" される画面など。
次の変更を訓練だと考えてください:調整→再生成→検証→出荷。目的は更新が日常的でリスクが低いと感じられるようにすることです。
繰り返すシンプルなループ:
- 小さな変更を一つ行う(1フィールド、1ルール、または1画面の挙動)。
- コードの整合性を保つために再生成する。
- クイックスモークテストを実行する(ハッピーパス+1つのエッジケース)。
- まずは安全な環境にデプロイする(ステージングやテストワークスペース)。
- 学んだことを短く記録する。
短い変更ログに決定理由を書いておくと後で数時間を節約できます。例:「チケット優先度はフリーテキストではなくenumで保存する、ラベルが変わってもレポートが壊れないようにする」など。
生成された出力を手作業で編集せずにこの練習をしたいなら、AppMasterで小さく閉じたモジュール(チケットフォーム、管理用リスト、簡単な承認ステップなど)を作り、各変更ごとに再生成してみてください。モデルが真実の源であるとき、アプリの進化がどれだけ楽になるか体感できるはずです。
要件に変化が多いなら、あなたの次の変更が良い練習の機会です。アプリの一角を選んで、今日から変更に強くしましょう。
よくある質問
パッチは、新しい要件をアプリに最小の編集でねじ込むことを指します。速く感じられますが、多くの場合データベース、API、ロジック、UIの間に不整合を生み、次の変更が遅くリスクが高くなります。
ここでの技術的負債とは、今日の構造が雑だったり一貫性がないために将来の変更で余計に支払うコストを指します。実装に時間がかかる、回帰のリスクが高まる、単純な変更でも多くのテストと調整が必要になる、といった形で現れます。
よくある兆候は、ほぼ同じ意味の重複フィールド、UIやエンドポイントに散らばったビジネスルール、そして削除されない「一時的」なフラグです。小さなルール変更で多くの無関係な箇所に手が入るなら、境界が信頼されていないサインです。
再生成優先とは、アプリを記述するモデル(データ、ロジック、UI)を編集し、それらの定義から出力(バックエンド、API、クライアント)を再生成することを意味します。こうすることで変更は予測可能になり、真実の源が一元化されます。
視覚的プロジェクト(モデルやプロセス)を真実の源と扱い、生成されたコードを出力として扱ってください。生成領域に手動で編集を加えると、再生成で失われるか、再生成を避けることで再びパッチ優先の習慣に戻ってしまいます。
将来も使われる安定した名詞から始め、名前を明確かつ一貫して付けましょう。現実に合った型を選び、監査用フィールド(created_at, updated_at, created_byなど)を早めに追加し、意味が重複するフィールドを避けることで混乱を後から直す必要が減ります。
ロジックは小さなプロセスに分けて、各ブロックが明確な入力と出力を持つようにします。隠れたフラグやどこかで設定される状態に頼らず、状態は明示的に渡すことで、1つのルールを変更しても他に波及しにくくなります。
UIは表示と入力に集中させ、ビジネスルールは共有ロジック(ワークフローやプロセス)に置きます。UIは「許可されているか」を見せられますが、実際に何が許可されるかはバックエンドのロジックが決めるべきです。そうすればルールが画面間でずれることを防げます。
実践的な順序は:データをモデル化する→読みやすいプロセスを作る→それらをエンドポイントでラップする→ユーザーのタスクに沿ってUIを構築する、です。各小さな変更の後に再生成し、短いエンドツーエンドのスモークテストを行えば、静かな壊れを早期に発見できます。
要件が頻繁に変わり、複数クライアント(Webとネイティブ)をサポートして一貫性を保ちたい場合に有効です。ノーコード的に試したいなら、AppMasterはデータモデル定義、ビジュアルロジック構築、フルソースコードの再生成を可能にしてくれるので、ワークフローを手作業のパッチに頼らず実践できます。


