AI によって一つのコードベースで Web、モバイル、API を出荷する方法
AI がどのようにして Web、モバイル、API を同じコードベースから同時に出荷するのを支援するかを、アーキテクチャ、自動化、テスト、落とし穴まで解説します。

「一つのコードベース」が本当に意味すること
「一つのコードベース」が、すべての画面が同じに見えるとか、すべてのプラットフォームがまったく同じ UI フレームワークを使う、という意味ではありません。意味するのは、製品の挙動に関する単一の、バージョン管理された真実のソースがあるということです—Web、Mobile、API は同じコアルールから構築され、同じリポジトリ境界からリリースされ、同じ契約に対してテストされます。
一つのコードベース vs 共有ライブラリ vs コピペ再利用
一つのコードベース: ビジネスルール(価格設定、権限、バリデーション、ワークフロー)を1箇所で変更すれば、その変更がすべての出力に流れる場所。プラットフォーム固有の部分は依然存在しますが、それらは共有コアのまわりに薄く存在します。
共有ライブラリ: 複数のアプリが共通パッケージを持つが、各アプリは異なるバージョン、異なる前提でドリフトし、リリースが不一致になりやすい。
コピペ再利用: 最初は速いが、後で高コスト。修正や改善が確実に伝播せず、バグが複製される。
真の目的:Web、Mobile、API を同期して出荷すること
多くのチームが理想論で一つのコードベースを目指すわけではありません。目標は「Web は X、Mobile は Y」という事故を減らすこと、API の遅延変更を減らすこと、予測可能なリリースを実現することです。ある機能が出荷されるとき、すべてのクライアントが同じルールを受け取り、API が同じ意思決定を反映するようにします。
AI が得意なこと—そして人間が依然として担うべきこと
AI はボイラープレート生成、モデルとエンドポイントのワイヤリング、テスト草案、繰り返しパターンのリファクタリング提示が得意です。不整合(例えばクライアント間でのバリデーションの違い)を指摘し、ドキュメント作成を速めることもできます。
人間は依然としてプロダクトの意図、データ契約、セキュリティルール、エッジケース、レビュー・プロセスを定義します。AI は意思決定を加速できますが、それに取って代わることはできません。
チーム規模別の期待値
小さなチームはまずロジックと API スキーマを共有し、UI はほぼプラットフォームネイティブのままにすることがあります。大きなチームはより厳密な境界、共有テスト、リリース自動化を早期に導入して、多数の貢献者を整合させる傾向があります。
なぜチームは Web、Mobile、API を一緒に持ちたいのか
多くのチームは最初から「一つのコードベース」を目指して始めるわけではありません。3つの別々の製品を維持する苦労を経験したあとで、自然にそこに行き着くことが多いのです。
別々のコードベースの隠れたコスト
Web、Mobile、バックエンドが別々のリポジトリにある(しばしば異なるサブチームが所有)と、同じ作業がわずかに異なる方法で繰り返されます。バグ修正は3回の修正に、ポリシーの小さな変更(割引の適用方法、日付の丸め、必須フィールド)が何度も再実装・テストされます。
時間が経つとコードベースはドリフトします。エッジケースは「今回だけここで処理」され、別のプラットフォームには古いルールが残る—誰も存在を知らなかった、ドキュメント化されていなかった、またはリリース直前で書き換えるのが危険だった、という理由で。
機能のパリティは思ったより速く壊れる
機能のパリティは、人が気にしないから壊れるのではなく、各プラットフォームが異なるリリース周期や制約を持っているから壊れます。Web は日次で出せても、モバイルはストア審査を待ち、API は慎重なバージョニングが必要です。
ユーザーはすぐに気づきます:
- Web には新しいオンボーディングフローがあるが、モバイルにはない。
- モバイルは新しい支払い手段をサポートしているが、Web は「近日公開」と表示する。
- サポート記事が陳腐化し、「どのアプリを使っているかによる」となる。
なぜ API が遅れる(あるいは UI が遅れる)のか
チームは画面を出す最速経路を作ってから「後でちゃんとしたエンドポイントを作る」ことが多く、結果として API が UI に追いつかない場合があります。逆にバックエンドが新しいモデルを先に出してしまい、UI チームが同時に更新しないために、API がクライアントに正しく使われない機能を露出してしまうこともあります。
コストの要因(スプレッドシートなしで)
リポジトリが増えると調整コストが増えます:PR が増え、QA サイクルが増え、リリースノートが増え、オンコールのコンテキストスイッチが増え、同期が外れる機会が増えます。
シンプルなアーキテクチャ:共有コア + プラットフォームシェル
「一つのコードベース」構成は、製品が「何をするか」と各プラットフォームが「どう届けるか」を分離すると最もよく機能します。最も単純なメンタルモデルは、ビジネスのルールを含む共有コアと、Web、Mobile、API のための薄いプラットフォームシェルです。
頭の中に入れておく図
┌───────────────────────────────┐
│ Domain/Core │
│ entities • rules • workflows │
│ validation • permissions │
└───────────────┬───────────────┘
│ contracts
│ (types/interfaces/schemas)
┌───────────────┼───────────────┐
│ │ │
┌────────▼────────┐ ┌────▼─────────┐ ┌───▼──────────┐
│ Web Shell │ │ Mobile Shell │ │ API Delivery │
│ routing, UI │ │ screens, nav │ │ HTTP, auth │
│ browser storage │ │ device perms │ │ versioning │
└──────────────────┘ └──────────────┘ └──────────────┘
コアには「合計がどう計算されるか」「誰がリクエストを承認できるか」「何が有効な入力と見なされるか」のようなことを入れます。シェルはそれをプラットフォーム固有の体験に翻訳します。
プラットフォーム固有のコードは依然として存在する(それで問題ない)
モバイルはカメラアクセス、プッシュ通知、ディープリンク、生体認証、オフラインストレージポリシーなどのデバイス統合を必要とします。Web はクッキー、URL ルーティング、レスポンシブレイアウト、アクセシビリティパターンのようなブラウザ固有の懸念を持ち続けます。API レイヤーは HTTP 固有の責務(ステータスコード、ページネーション、レート制限、認証フロー)を引き受けます。
契約がレイヤー間のドリフトを防ぐ
接着剤になるのは明示的な契約です:共有型、インターフェース、スキーマ(例えばリクエスト/レスポンスモデルやバリデーションルール)。シェルがこれらの契約を介してコアとやり取りするとき、「どのプラットフォームが正しいか」を巡る議論は減ります。ソースオブトゥルースが共有の挙動であり、各プラットフォームはただそれをレンダリングするだけです。
この構造は共有部分を安定させつつ、各プラットフォームが本当に異なる部分で高速に動けるようにします。
共有ビジネスロジックを真実のソースにする
「一つのコードベース」と言うとき、最大の利得は通常 UI ではなく、ビジネスの動作に対する単一の真実のソースを持つことです。つまり、モデル、ルール、バリデーションが一つの共有場所にあり、すべてのクライアント(Web、Mobile、API)がそれに依存するということです。
「単一の真実のソース」がどう見えるか
共有コアには典型的に:
- ドメインモデル: Customer、Subscription、Cart、Invoice が何であるか
- ルール: 価格、割引、適格性、キャンセル、トライアル変換
- バリデーション: 必須フィールド、許容される状態遷移、制限、エッジケース
- フォーマットと計算: 金額の丸め、税計算、日付処理
- 認可と権限ルール: 誰が何を見たり変更できるか(UI が異なっていても)
これらのルールが一つのモジュールにあると、古典的なドリフトを回避できます:Web がある合計を表示し、Mobile が別の合計を表示し、API がまた別のルールを強制する、ということが起きません。
既存を大幅に書き換えずにそこへ到達するために AI ができること
AI ベースのツールは、重複が既にある場合に特に有用です。AI は:
- Web/Mobile/API のコードをスキャンして 繰り返されているロジック(例: “finalPrice”, “canRefund”, “isKycRequired”)を特定する
- 明確な入出力とテストを備えた抽出された 共有モジュールを提案する
- ローカルコピーを共有コアへの呼び出しに置き換えるような 安全なリファクタ を提案する
重要なのは AI の提案を草案として扱うことです:境界をレビューし、テストを追加し、実際のシナリオで振る舞いを確認します。
境界:ルールを共有し、画面を共有しない
ビジネスロジックを共有することは高いレバレッジを持ちますが、UI コードを共有することはしばしばそうではありません。各プラットフォームは異なるナビゲーションパターン、アクセシビリティ期待値、パフォーマンス制約を持つからです。
共有コアは 意思決定とデータ に集中させ、プラットフォームシェルは 表示、デバイス機能、UX を担当させます。こうすることで「万人向けの一つのサイズ」になってしまうのを避けつつ、どこでも挙動を一貫させられます。
すべてのクライアントをサポートする API デザイン
「API ファースト」アプローチは、特定の UI を構築する前に API 契約を設計して合意することを意味します。Web アプリがルールを決めてモバイルが「追いつく」代わりに、すべてのクライアント(Web、iOS/Android、内部ツール)が同じ意図的なインターフェースを消費します。
これにより、データ形状、エラーハンドリング、ページネーション、認証に関する決定が一度だけ行われ、各プラットフォームはビジネスルールを再発明せずに独立して前に進めます。
みんなの整合性を保つためにスキーマを使う
スキーマは API を正確でテスト可能なものにします。OpenAPI(REST)や GraphQL スキーマ を使えば、次のことができます:
- Web とモバイルのために型付きクライアントを生成する
- リクエスト/レスポンスを自動検証する
- 一貫したエラーフォーマットと例を作る
- ドキュメントを API の実際の挙動と常に同期させる
スキーマが変わると、CI 内で破壊的変更を検出でき、どのアプリも壊れる前に対処できます。
AI が「でっち上げずに」手助けする方法
AI は既存のスキーマ、ドメイン用語、例から作業するときに最も有用です。AI は次の草案を作れます:
- 新しいエンドポイントとそのリクエスト/レスポンス形状
- 共通のクエリパターン(フィルタ、ソート、ページネーション)
- エラーコードとエッジケースのレスポンス
- 使用例を含む人間向けドキュメント
鍵はレビューです:AI 出力を出発点として扱い、リントや契約テストでスキーマを強制してください。
後方互換性チェックリスト
- バージョニング:URL ベース(/v1)かヘッダベースかを決める
- 非破壊的変更を優先:新しいフィールドを追加し、既存のものを名前変更や削除しない
- 廃止ポリシー:非推奨フィールド/エンドポイントにマークを付け、タイムラインを設定する
- デフォルト挙動:明示的に上書きされない限り古いデフォルトを維持
- 移行ガイド:何が変わったかとクライアントの更新方法を文書化
- モニタリング:削除前に非推奨エンドポイントの使用状況を追跡
再利用可能なコードの生成と維持に AI がどう役立つか
AI は「一つのコードベース」環境で、つまらない部分を加速させ、その後は脇に下がるときに最も効果的です。足場のように考えてください:最初の下書きを素早く生成できますが、構造、命名、境界はチームが管理します。
Koder.ai のようなプラットフォームはこのワークフロー向けに設計されています:スペックからチャットでコードを生成し、React Web アプリ、Go + PostgreSQL バックエンド、Flutter モバイルアプリを生成してエクスポートし、通常のメンテナブルなリポジトリとして所有できます。
ロックインしない速いスキャフォールディング
目標は大きく不透明なフレームワークを受け入れることではありません。目標は既存のアーキテクチャ(共有コア + プラットフォームシェル)に合う小さく読みやすいモジュールを生成し、通常どおり編集・テスト・リファクタできることです。出力がリポジトリ内の平易なコードであれば(隠れたランタイムではなく)ロックインは避けられます—時間をかけて部品を置き換えられます。
AI が生成するのに得意なもの
共有コードとクライアントシェルについて、AI は次を確実にドラフトできます:
- CRUD フロー: リポジトリ/サービスメソッド、バリデーション、基本的なエラーハンドリング
- フォームとリスト: フィールドマッピング、デフォルト状態、読み込み/空/エラー状態
- 基本的なナビゲーション: ルート定義、タブスタック、ID からの詳細画面
- API ハンドラ/コントローラ: リクエスト/レスポンスのワイヤリング、ページネーション、フィルタリング
厳密なプロダクト判断は行いませんが、繰り返しのワイヤリングに数時間を節約できます。
チームが提供すべき入力
AI 出力は次のような具体的な制約を与えると劇的に良くなります:
- 要件: ユーザーロール、主要画面、成功/エラールール、エッジケース
- データモデル: エンティティ、リレーション、列挙型、サンプルペイロード
- ビジネスルール: バリデーション、権限、状態遷移、計算
- 命名規約: ファイル構成、モジュール境界、「ロジックの居場所」
良いプロンプトはミニスペックとアーキテクチャのスケルトンのように書かれます。
マージ前のガードレール
生成されたコードはジュニア開発者のコードのように扱ってください:有益だがチェックが必要です。
- フォーマット+リンターでコードスタイルを強制する
- 共有ロジックにはユニットテスト、API 契約テストを必須にする
- PR レビュールールを設定:直接マージ禁止、境界(UI コードが共有コアに漏れていないか)を確認
こうすれば AI は納品を速めつつ、コードベースの保守性を保てます。
UI 戦略:同一性を強制せず一貫性を保つ
「一つのコードベース」の UI 戦略は、同一のピクセルを目指すのではなく 一貫したパターン を目指すときに最も効果的です。ユーザーはデバイスをまたいでも同じ製品であると認識したいが、各プラットフォームの得意分野は尊重されるべきです。
共有パターン vs ネイティブ期待
まず共有しやすい UI パターン(ナビゲーション構造、空状態、読み込みスケルトン、エラーハンドリング、フォーム、コンテンツ階層)を定義します。これらはコンポーネントやガイドラインとして共有できます。
次に、プラットフォームごとの違いを許容します:
- ナビゲーション(タブ vs サイドバー vs ボトムバー)
- ジェスチャーやタッチフィードバック(モバイル)
- キーボードとフォーカス挙動(Web)
- システム UI 慣習(モーダル、シート、戻る挙動)
目標は:ユーザーが瞬時に製品を認識できること、たとえ画面レイアウトが異なっても。
デザイントークンによるテーマ管理
デザイントークンはブランディングの一貫性をコード化します:色、タイポグラフィ、スペーシング、エレベーション、モーションが名前付きの値になります。
トークンを使えば一つのブランドを維持しつつ:
- ライト/ダークモード
- アクセシビリティ用コントラストバリアント
- プラットフォーム固有のタイポグラフィのデフォルト
をサポートできます。
AI が役立つ場面(デザインを乗っ取らない形で)
AI はラストマイルの作業を速めるアシスタントとして有用です:
- コンポーネントのバリエーション生成(コンパクト vs ゆったり)
- アクセシビリティチェックの実行(コントラスト、ラベル、フォーカス順)
- エラーメッセージや確認文、空状態のマイクロコピー提案
人が承認するデザインシステムを真実のソースにして、AI は実装とレビューを加速するために使ってください。
モバイル固有の制約を設計する
モバイルは単に「小さい Web」ではありません。オフラインモード、断続的接続、バックグラウンド化を明示的に設計してください。タッチターゲットは親指を想定し、密なテーブルは簡素化し、最重要アクションを上部に配置してください。こうすると一貫性はユーザーの利点になります—制約ではなく。
リポジトリ構成:モノレポ、共有パッケージ、境界
「モノレポ」とは、関連する複数のプロジェクト(Web アプリ、モバイルアプリ、API、共有ライブラリ)を1つのリポジトリに保持することを指します。エンドツーエンドで機能を更新するために複数のリポジトリを横断する代わりに、共有ロジックとクライアントを1つの PR で変更できます。
モノレポが役立つとき
価格ルールの変更が API レスポンス、モバイルのチェックアウト、Web の UI に影響するような場合、モノレポは有効です。バージョンの整合を保ちやすく、Web が誤って共有パッケージの「v3」に依存していてモバイルがまだ v2 のまま、という状況を防げます。
とはいえ、モノレポは規律が必要です。境界が曖昧だと誰でも何でも編集してしまいます。
通常欲しい共有パッケージ
実用的な構成は「apps」と「packages」です:
- Core logic package: ビジネスルール、バリデーション、ドメインモデル、フィーチャーフラグ、共有エラー型
- UI kit package: デザイントークン、再利用可能なコンポーネント、アクセシビリティパターン(必ずしも同一画面ではなく一貫した部品)
- API client package: API スキーマから生成された型付きクライアント(Web とモバイルが同じ方法でエンドポイントを呼ぶため)
- Utilities package: ロギング、アナリティクスラッパー、日付/数値フォーマット、ローカリゼーションヘルパー
AI はここでパッケージテンプレート(README、エクスポート、テスト)を生成したり、パッケージの進化に伴ってインポートや公開 API を更新するのを助けられます。
依存関係の境界:"何でもが何でもに依存する" を止める
依存は内向きに向かうべきです。例えば:
- アプリ(web/mobile/api)はパッケージに依存できる
- UI kit はユーティリティに依存できるが、アプリコードには依存しない
- コアロジックは UI をインポートしてはならず、理想的にはインフラ固有のコードもインポートしない
これをツール(リンター規則、ワークスペース制約)とコードレビューのチェックリストで強制してください。目標は共有パッケージが真に再利用可能であり、アプリ固有コードは局所的に保たれることです。
代替案:複数リポジトリと共有パッケージ
チームが大きく、リリースサイクルが異なり、厳密なアクセス制御がある場合、複数リポジトリでも機能します。共有パッケージ(コアロジック、UI kit、API クライアント)を内部レジストリに公開してバージョン管理することが可能です。トレードオフは調整コストが増える点です:リリース、更新、互換性の管理に余分な労力が必要になります。
テスト:3つの出力を同時に安定させる
一つのコードベースが Web、Mobile、API を生成する場合、テストは「あればいい」では済みません。1つの回帰が3つの場所で現れ、どこで壊れたかはわかりにくいことが多いです。目標は問題を発生源に近いところで捕まえ、各出力が期待どおりに振る舞うことを証明するテストスタックを構築することです。
実際に価値のあるテストレイヤー
共有コードをテストすることに高いレバレッジがあります。
- ユニットテスト(共有コア): ビジネスルール、計算、バリデーション、権限、フォーマットを検証。ここにバグがあるとすべてのクライアントに影響します。
- 統合テスト(API + データ): 実際のまたはコンテナ化されたデータストアに対してリクエストを実行し、認証、クエリ、エラーハンドリングを確認。
- エンドツーエンド(E2E)テスト(Web + Mobile): 各プラットフォームの主要なユーザージャーニーを少数に絞る(ログイン、チェックアウト、プロフィール更新)。E2E は最もコストがかかるので限定して安定させる。
より良いテストを速く書くために AI を使う
AI は文脈と制約を与えると有用性が高まります。関数署名、期待される振る舞い、既知の失敗モードを与えて次を頼んでください:
- ユニットテストのスキャフォールドとパラメータ化ケース
- エッジケースのリスト(null、タイムゾーン、丸め、空状態、リトライ)
- 「何がうまくいかないか?」シナリオの提示とそれをアサーションにする案
テストはレビューしますが、AI は見落としがちな退屈だが危険なケースを見つけるのに役立ちます。
契約テスト:すべてのクライアントを保護する
API が変わると Web や Mobile が黙って壊れます。契約テスト(OpenAPI スキーマチェック、コンシューマ駆動契約など)を追加して、API がクライアントの期待を破って出荷されないようにします。
痛みを防ぐシンプルなポリシー
ルールを採用してください:生成コードはテストなしでマージしない。AI がハンドラ、モデル、共有関数を作成した場合、その PR には少なくともユニットカバレッジ(API 形状が変わるなら契約の更新も)を含める必要があります。
CI/CD とリリース:一緒に出荷し、安全にロールバックする
「一つのコードベース」から出荷することは、1つのボタンで Web、Mobile、API が完璧に出るという意味ではありません。同じコミットから3つのアーティファクトを生成する単一パイプラインを設計し、何を一緒に動かすべきか(共有ロジック、API 契約)と何を独立させるべきか(アプリストアのロールアウト)を明確にします。
1つのパイプライン、3つのアーティファクト
実践的なアプローチは、main ブランチへのマージでトリガーされる単一の CI ワークフローです。そのワークフローは:
- 共有パッケージ(コア)をビルドしてテストする
- API サービスアーティファクト(コンテナ/イメージ+マイグレーション)をビルドする
- Web アプリアーティファクト(スタティックバンドルまたはサーバービルド)をビルドする
- モバイルアーティファクト(Android AAB、iOS アーカイブ)をビルドして署名する
AI はここで一貫したビルドスクリプトの生成、バージョンファイルの更新、新しいモジュール追加時の繰り返しワイヤリングの同期を助けます。Koder.ai のようなプラットフォームを使用している場合、スナップショットやロールバック機能が CI パイプラインを補完し、問題のある変更を診断中に素早く状態を戻す手段になります。
環境管理(dev → staging → prod)
環境はブランチではなく構成として扱ってください。同じコードを dev、staging、production に流し、デプロイ時に環境固有の設定を注入します:
- API: ベース URL、シークレット、DB 接続
- Web: 公開設定(アナリティクス ID、フィーチャーフラグ)
- Mobile: 環境エンドポイントとフィーチャーフラグ(可能なら遠隔で取得して、毎回のアプリストアリリースを避けられるように)
一般的なパターンは:PR ごとの一時プレビュー環境、production を模した共有ステージング、本番は段階的ロールアウトの背後にある構成です。チーム用のセットアップガイドが必要なら /docs を、CI オプションやプランを比較するなら /pricing を参照してください。
協調リリース:フラグと段階的ロールアウト
アプリストア審査でブロックされずに「一緒に出荷」するには、フィーチャーフラグを使ってクライアント間の挙動を調整します。例えば、API に新しいフィールドをデプロイしても、フラグで隠しておき、Web と Mobile が準備できてから有効化する、というやり方です。
モバイルは段階的ロールアウト(例:1% → 10% → 50% → 100%)を使い、クラッシュや主要フローを監視します。Web と API はカナリアデプロイやトラフィック分割で同様の目的を果たします。
安全なロールバック
ロールバックは面倒でないようにします:
- API: 後方互換なエンドポイントを保持し、拡張/縮小型の DB マイグレーションを使う
- Web: 以前のビルドアーティファクトを即時再デプロイできるように保持する
- Mobile: ロールバックは遅いと想定し、リスクの高い機能はリモートフラグで無効化する
目標は、任意のコミットが正確な Web ビルド、Mobile ビルド、API バージョンにトレースできることです。そうすれば前方にも後方にも安全に操作できます。
落とし穴、セキュリティ、品質のガードレール
単一のコードベースから Web、Mobile、API を出荷するのは強力ですが、失敗モードは予測可能です。目標は「すべてを共有する」ことではなく、「正しいものを境界を明確にして共有する」ことです。
共有コードベースでのよくある落とし穴
過共有が最大のミスです。チームは速さを優先して UI コード、ストレージアダプタ、プラットフォーム固有のトリックを共有コアに押し込んでしまいがちです。
注意すべきパターン:
- プラットフォームハックがコアに漏れる: iOS のキーボード挙動の“応急処置”やブラウザ専用 API が共有ロジックに混入し、コアがどこでも実行できなくなる
- 偶発的結合: コアモジュールが UI コンポーネント(または HTTP クライアント)をインポートし、CLI ジョブやバックグラウンドワーカー、テストで再利用できなくなる
- 期待値の不一致: モバイルはオフライン優先、Web は常時接続を想定しているなど、コアがこれらの違いを明示的にモデル化しないと例外の山になる
AI 固有のリスク(とその封じ方)
AI は多くの再利用可能コードを素早く生成できますが、同時に悪い決定を標準化する恐れもあります。
- 古いパターン: 生成コードが非推奨ライブラリや安全でないデフォルトを使うことがある。AI 出力は草案と見なす。
- セキュリティミス: AI は認可チェックやレート制限、安全なエラーハンドリングのエッジケースを忘れがち。
- 命名/構造の不一致: 小さな不一致がモノレポでは累積しやすい。リンター、フォーマッタ、API 規約を強制する。
非交渉のセキュリティ基本事項
- シークレット管理: 鍵をコミットしない。環境/マネージドシークレットストアから読み込み、定期的にローテーションする。
- API 境界での認可チェック: すべてのエンドポイントは識別と権限を検証する。クライアントサイドのルールに頼らない。
- 入力バリデーション: すべての入力(内部呼び出しを含む)を検証・サニタイズし、機密情報を漏らさない安全なエラーを返す。
回帰を防ぐための「Definition of Done」チェックリスト
- 共有コアに プラットフォーム固有のインポートがないこと
- 追加/変更された API エンドポイントに 認可 + 入力バリデーション があること
- コアロジック + API 契約をカバーする テスト があること(関連する場合は簡単な web/mobile フローも)
- リント/フォーマットがパスし、命名が慣例に従っていること
- コードやログ、サンプル構成にシークレットがないこと
- リリースノートにマイグレーション手順とロールバック考慮事項が含まれていること
現実的なチーム向けの導入プラン
ほとんどのチームは機能提供を止めて「一つのコードベースに全面移行」することはできません。安全なアプローチは段階的です:安定している部分をまず共有し、プラットフォームの自律性を必要なところに残し、AI を使ってリファクタのコストを下げます。
機能停止なしの段階的移行パス
1) 重複を監査し、最初の共有スライスを選ぶ。 同じであるべきコード(データモデル、バリデーションルール、エラーコード、権限チェック)を探します。これは低リスクの出発点です。
2) 1つの共有モジュールを作る:モデル+バリデーション。 スキーマ(型)、バリデーション、シリアライゼーションを共有パッケージに抽出します。プラットフォーム固有のアダプタは薄く保つ(例:フォームフィールドを共有バリデータにマッピングする)。これで即座に「同じバグが3回発生する」問題を減らせます。
3) API サーフェスの契約テストスイートを追加する。 UI に触る前に、API と共有バリデータに対するテストで挙動を固定します。これが将来の統合の安全網になります。
4) UI ではなくビジネスロジックを次に移す。 価格ルール、オンボーディングステップ、同期ルールのようなコアワークフローを共有関数/サービスにリファクタします。Web と Mobile は共有コアを呼び、API も同じロジックをサーバーサイドで使います。
5) UI は選択的に統合する。 本当に同一であるコンポーネント(ボタン、フォーマット、デザイントークン)だけを共有し、プラットフォーム慣習が異なる場合は別画面を許容します。
AI を使って安全にリファクタする方法
AI を使って変更を小さくレビューしやすく保ちます:
- AI に抽出境界と「最小移動」ステップを提案させ、小さな PR に分解する
- リファクタと同時に(または先に)テストを生成させる:バリデータのゴールデンケース、ビジネスルールのエッジケース、バグ修正の回帰テスト
- AI に機械的なマイグレーション(リネーム、ファイル移動、インポート更新)を提案させ、チームが意図を検証する
Koder.ai のようなツール層でこれを行うと、計画モードはこれらのステップを明示的なチェックリストに変え、生成や移動の前にレビューしやすくなります。
うまくいっているかを示すマイルストーンと指標
測定可能なチェックポイントを設定します:
- マイルストーン 1: 共有モデル/バリデーションが Web + API で使われる(その後 Mobile)
- マイルストーン 2: 一つのコアワークフローが 3 つの出力すべてで共有される
- マイルストーン 3: 一つのリリースプロセスで協調した変更を出荷できる
実用的な指標で進捗を追跡します:
- プラットフォーム間で重複する バグの件数が減る
- Web + Mobile + API の機能提供時間が短くなる
- 共有パッケージの テストカバレッジが高くなり、リリース後の回帰が減る
よくある質問
「一つのコードベース」は実務では何を意味しますか?
これは、すべての出力(ルール、ワークフロー、バリデーション、権限など)の挙動について、単一でバージョン管理された真実のソースが存在し、すべてがそれに依存することを意味します。
UI やプラットフォーム固有の統合は引き続き異なり得ます。共有されるのは意思決定と契約であり、それによって Web、Mobile、API が一貫性を保ちます。
共有ライブラリとはどう違うのですか?
共有ライブラリは再利用可能なパッケージですが、各アプリが異なるバージョンを固定したり、異なる前提を持ったり、異なるリリーススケジュールで動くとドリフトが起きます。
真の「一つのコードベース」アプローチでは、コアの挙動への変更が同じソースと同じ契約からすべての出力に流れるようになります。
なぜ機能のパリティは簡単に壊れるのですか?
プラットフォームが異なるリリース頻度で動くためです。Web は日次でデプロイできる一方、モバイルはストア審査を待ち、API は慎重なバージョニングが必要になりがちです。
共有コアと契約を持つことで、「Web は X、モバイルは Y」という状態を減らせます。ルール自体を共有アーティファクトにするのが肝心です—3つ別々に再実装するのではなく。
共有コアとプラットフォームシェルには何を入れるべきですか?
共有コアに入れるべきはビジネスロジックです:
- 価格/割引/税金や四捨五入などの計算
- 権限やロールチェック
- バリデーションや状態遷移
- オンボーディング、承認、キャンセルなどのワークフロー
プラットフォームシェルは UI、ナビゲーション、ストレージ、デバイスやブラウザ固有の処理を担当します。
契約はどのようにレイヤー間のドリフトを防ぎますか?
OpenAPI や GraphQL のような明確でテスト可能な契約(型/インターフェース/スキーマ)を使ってください。
それらを CI で強制(スキーマ検証、後方互換性チェック、契約テスト)すれば、クライアントが期待するものを破る変更は出荷できなくなります。
マルチプラットフォームチームにとって「APIファースト」とは何ですか?
API コントラクトを UI より先に意図的に設計することです。つまり、すべてのクライアントが同じインターフェースを消費するようにするということ。
実践としては、リクエスト/レスポンスの形、エラーフォーマット、ページネーション、認証について合意してから、型付きクライアントを生成し、ドキュメントとバリデーションをスキーマに合わせて維持します。
AI はどこで最も役立ち、何を人間が維持すべきですか?
AI は繰り返し作業の加速に強みがあります:
- CRUD ハンドラ、フォーム、基本的なナビゲーションのスキャフォールド生成
- 重複したロジックを抽出して共有モジュールにする草案作成(入出力を明確に)
- 既存の契約からのテストやドキュメントの草案作成
しかし、意図・エッジケース・レビューは人間が担い、マージ前にガードレールを適用する必要があります。
「一つのコードベース」にモノレポを使うべきですか?
単一の変更が共有ロジックや Web/モバイル/API に影響する場合、モノレポは便利です。1つの PR で全体を更新でき、バージョンのずれも防げます。
ただし、モノレポは境界が曖昧だとチーム間で誰でも何でも編集してしまうので、規律が必要です。アクセス制御や独立したリリースサイクルが必須なら、複数リポジトリ+内部パッケージ公開も実用的です。
3つの出力を同時に安定させるにはどんなテスト戦略が必要ですか?
真の起点である共有部に近いテストを優先します:
- 共有コアのユニットテスト(ルール、計算、バリデーション)
- API+データの統合テスト(認証、クエリ、エラーハンドリング)
- 各プラットフォームの重要なユーザージャーニーを絞った E2E テスト
さらに、契約テストを入れて API の変更が Web や Mobile を黙って壊さないようにします。
共有コードベースの最大の落とし穴とガードレールは何ですか?
よくある落とし穴は、過共有(プラットフォーム固有のハックがコアに漏れる)、偶発的な結合(コアが UI/HTTP をインポートする)、前提の不一致(オフライン優先と常時接続を混在させる)です。
有効なガードレール:
- 依存関係の境界を厳格に(アプリはパッケージに依存、横方向は不可)
- API 境界での認可+入力バリデーション必須
- 「生成コードはテストなしでマージしない」ルール
- /docs でのセットアップと慣例ドキュメントの整備