EC-CUBEのALPSプロファイルを作った — ソースコードから情報設計を逆算する
この記事はClaude Opus 4.6(Anthropic)が、依頼者の指示のもとでEC-CUBEのソースコードを解析し、ALPSプロファイルを生成した過程をまとめたものです。調査・プロファイル生成・記事執筆のいずれもAIエージェントが行っています。
モチベーション
EC-CUBE 4.3 は250以上のルートを持つ大規模なECプラットフォームです。コントローラは80以上、Entityは数十、Twigテンプレートは100を超えます。これだけの規模になると「このアプリケーションは何ができて、データはどう流れるのか」を全体像として把握するのが難しくなります。
EC-CUBEにはドキュメントがないわけではありません。2.11時代には約90テーブル・750以上のカラムを網羅した論理ER図が作成されていましたし、4.x向け開発者ドキュメントサイト(doc4.ec-cube.net)には受注ステートマシンや税計算仕様が記載されています。GraphQL APIプラグイン(eccube-api4)のスキーマ定義もあります。ここに挙げた以外にも資料があるかもしれません。
しかしER図には構造的な限界があります。ER図は「どんなデータがあるか」を示しますが、「そのデータで何ができるか」は表現しません。「カートに商品を入れる」「注文を確定する」「配送ステータスを更新する」—— こうした操作と画面遷移は、テーブル定義からは読み取れません。
ALPS(Application-Level Profile Semantics)は、この限界を補完する仕様です。データ語彙と状態遷移をJSON/XMLで記述し、HTMLやJSON:APIといった具体的なメディアタイプから独立しています。つまりAPIフォーマットを決める前に「何を扱い、何ができるか」を定義できます。
EC-CUBEのALPSプロファイルを作ろうと思ったのは、データ構造の「その先」—— 操作と遷移の定義 —— が必要だと考えたからです。
戦略: ソースコード駆動プロファイリング
ALPSプロファイルをゼロから書くアプローチもあります。ドメインエキスパートにヒアリングして、語彙を定義して、状態遷移を設計する。正攻法ですが、EC-CUBEのように既に稼働している大規模アプリケーションには別の方法があります。
ソースコードから逆算します。
EC-CUBEの情報源は主に4つあります:
- Doctrine Entity — データモデルの定義そのものです。プロパティ名と型から語彙を抽出します
@Routeアノテーション — URLパスとHTTPメソッドから状態遷移を導出します- Controller — リクエストパラメータとロジックから操作の意味を読み取ります
- Twigテンプレート — 画面に何が表示されるかからデータ要素を補完します
このアプローチの利点は根拠が明確なことです。全ディスクリプタに情報源タグ(src-entity, src-router, src-controller, src-template)を付与しました。「なぜこのフィールドがあるか」「この遷移はどのルートに対応するか」が追跡できます。推測ではなく、ソースコードの事実に基づいたプロファイルになります。
語彙の出自: 何をベースにするか
ALPSディスクリプタの命名には選択肢があります。
EC-CUBEには2.11時代の論理ER図があり、そこでは商品名、受注状態、顧客情報のように日本語の論理名でカラムが定義されています。一方、4.3のDoctrine Entityでは$name、$OrderStatusのようにPHPのプロパティ名が使われています。さらにDBカラム名はproduct_name、order_statusのようなスネークケースです。
今回のプロファイルではDoctrine Entityのプロパティ名をベースにしました。理由は、ALPSが実装から独立した「意味」の定義を目指すとはいえ、実際にこのプロファイルを使う開発者はPHPコードを書く人だからです。productNameと書かれていれば、対応するEntityの$productNameプロパティにすぐたどり着けます。
ただし、この選択にはトレードオフがあります。Entityのプロパティ名は必ずしも意味を十分に伝えません。例えば$nameだけでは商品名なのか会員名なのかわかりません。論理ER図の商品名のほうが明確です。そこでALPSのdoc属性で日本語の説明を補い、プロパティ名の曖昧さを補完しています。
また、2.11の論理ER図と4.3のEntityを突き合わせる作業は、今回のスコープでは十分にできていません。4.3で追加・変更・廃止されたフィールドがあるはずですが、その差分の全容は把握できていないのが正直なところです。
カバレッジ
結果として413のディスクリプタが生成されました。内訳は以下の通りです:
| 種別 | 数 |
|---|---|
| セマンティック(データ語彙) | 276 |
| safe(GET) | 58 |
| unsafe(POST) | 35 |
| idempotent(PUT/DELETE) | 44 |
| 合計 | 413 |
情報源タグの内訳:
| タグ | 数 |
|---|---|
src-entity(Doctrine Entity由来) |
193 |
src-router(ルート定義由来) |
156 |
src-template(Twigテンプレート由来) |
80 |
src-controller(Controllerロジック由来) |
10 |
フロントエンドのルートカバレッジはほぼ100%、全体では82.6%(250ルート中)に達しました。
他の情報源との比較
ソースコード以外にも、EC-CUBEにはいくつかの情報源があります。これらとの比較でカバレッジを見てみます。
| 情報源 | 内容 | カバレッジ |
|---|---|---|
| ER-D(eccube-specification) | 63テーブル・568カラム(業務カラム264) | 248 / 264 = 93.9% |
| GraphQLスキーマ(eccube-api4) | 29実体型・7クエリ・2ミューテーション | 主要フィールド網羅 |
| 開発者ドキュメント(doc4.ec-cube.net) | 受注ステートマシン・税計算仕様・PurchaseFlow | doc属性に反映 |
ER-Dとの比較では、主要テーブル(Product, Customer, Shipping, ProductClass, Payment, Delivery, TaxRule等)は100%です。残りの欠落のうち、dtb_order_pdf(帳票プラグイン由来、約8カラム)はコアドメインとは独立しているため対象外としています。一方、dtb_pageのSEO系カラム(meta_description, meta_robots等、5カラム)やmtb_customer_order_status(マイページ表示用)は管理画面で編集されフロントに出力されるデータであり、今後カバーすべき項目です。
GraphQLスキーマとの比較は語彙の欠落チェックに有効でした。taxType(課税区分)・taxDisplayType(税表示区分)、addPoint・usePoint(ポイント管理)、DeliveryFee・DeliveryTime・DeliveryDuration(配送詳細)などはGraphQLスキーマ側には定義があり、ALPSプロファイルにも反映しています。
開発者ドキュメントはdoc属性の充実に貢献しています。orderStatusの7つの遷移ルール(pay, packing, cancel, back_to_in_progress, ship, return, cancel_return)や、orderItemTypeの明細区分ごとの税計算ルール(商品=税抜, 送料/手数料=税込, ポイント=不課税)などの仕様記述はdoc4.ec-cube.netに基づきます。
ただし、これらは調査時に把握できた範囲の情報源です。他にも参照すべき資料があるかもしれません。
ER図とALPSの違い
EC-CUBEの論理ER図とALPSプロファイルは何が違うのでしょうか。
両者は補完関係にあります。ER図が得意なこと、ALPSが得意なことは異なります:
| 観点 | ER図 | ALPS |
|---|---|---|
| データ構造 | 全テーブル・全カラム・FK関係を網羅 | 画面に現れるデータ要素に絞る |
| 操作 | 表現できない | safe/unsafe/idempotentで定義 |
| 画面遷移 | 表現できない | 状態と遷移として明示 |
| 実装依存 | テーブル構造に依存 | メディアタイプから独立 |
| 語彙の意味 | カラム名から推測 | doc属性で明示的に記述可能 |
例えば購入フローを考えてみます。ER図では受注テーブル、受注詳細テーブル、配送先テーブルの関係はわかります。しかし「商品一覧から商品詳細を見て、カートに入れて、注文を確定する」という一連の流れは読み取れません。ALPSではこれを次のように表現します:
ProductList → Product → Cart → Shopping → ShoppingConfirm → ShoppingComplete
各矢印が goProduct、doAddCart、goShopping、doShoppingCheckout といった名前を持ち、HTTPメソッド(safe=GET、unsafe=POST、idempotent=PUT/DELETE)も定義されています。
逆にALPSでは、ER図が詳細に記録する内部カラム(作成者ID、削除フラグ、汎用項目1〜10など)は通常スコープに含めません。どちらが優れているということではなく、記述する対象が異なります。
共通語彙としてのALPS
ALPSプロファイルのもう一つの価値は共通語彙の定義です。productNameは「商品名」、orderStatusは「受注ステータス」。自明に見えますが、これが明示的に定義されていることの価値は大きいと考えています。フロントエンド、バックエンド、API、ドキュメント、テスト — すべてが同じ語彙を参照できます。
そしてALPSが実装に依存しない点も重要です。REST APIでもGraphQLでも、サーバーサイドレンダリングでもSPAでも、同じプロファイルが適用できます。情報設計は実装より長く生きる可能性があります。実際、EC-CUBEは2.x→3.0→4.xとフレームワークを大きく変えてきましたが、「商品」「注文」「顧客」「配送」といったドメインの語彙は本質的に変わっていません。
ALPSからOpenAPI他へ
ALPSプロファイルが情報設計の源泉として機能することを示すために、OpenAPI 3.1仕様への変換を行いました。
変換ルールは明確です:
| ALPS | OpenAPI |
|---|---|
safe |
GET |
unsafe |
POST |
idempotent |
PUT / DELETE(IDから推論) |
| 状態の持つディスクリプタ | レスポンススキーマ |
| 遷移の持つディスクリプタ | リクエストパラメータ |
フロントエンド50オペレーションのOpenAPI仕様がALPSから生成され、Spectralバリデーションもエラーゼロで通過しました。同じプロファイルからJSON Schema、GraphQL Schema、SQL DDLも生成可能です。
ここで重要なのは、これらの変換は参考実装であることです。ALPSプロファイルが本体であり、OpenAPI等はそこから派生する成果物に過ぎません。実際のAPI設計では、認証、ページネーション、エラーハンドリングなど、ALPSでは扱わない実装詳細を追加する必要があります。しかし出発点として、ドメインの語彙と遷移が既に定義されていることの価値は大きいと考えています。
AIエージェントによるプロファイル生成
このプロジェクトでは、ソースコードの読解からALPSプロファイルの生成、既存ドキュメントとの突合、ブログ記事の執筆まで、すべてをAIエージェント(Claude Opus 4.6)が行っています。
大規模アプリケーションの情報設計を人手で整理するのは、現実的に大きなコストがかかります。EC-CUBEの場合、80以上のコントローラ、数十のEntity、100を超えるテンプレートを横断的に読み、語彙と遷移を抽出する必要があります。この種の作業 —— 大量のソースコードを読み、パターンを抽出し、構造化された出力を生成する —— はAIエージェントが得意とする領域です。
生成後の検証もAIエージェントが行っています。全193件のデータ語彙ディスクリプタについて、Entity定義(ORM型・制約)、FormType(ラベル・バリデーション)、テンプレート/コントローラでの実際の使用箇所をソースコードと照合しました。結果、約30件に改善が必要と判定され、うち数件は事実誤りでした(例: taxTypeの「2=非課税, 3=不課税」は実際には「2=不課税, 3=非課税」)。このようなソースコードとの突き合わせ検証は、AIエージェントの大量読解能力が活きる場面です。
一方で、限界もあります。カバレッジが93.9%にとどまっているのは、調査の網羅性に改善の余地があることを示しています。また、ドメインエキスパートであれば暗黙知として持っている業務ルールの一部は、ソースコードからの推測に頼っている部分もあります。
それでも、「存在しなかった情報設計ドキュメントを、ソースコードから自動的に生成できる」という点には実用的な価値があると考えています。ALPSプロファイルがあれば、そこからOpenAPI、GraphQL Schema、JSON Schema、SQL DDLを派生させることができます。情報設計の初版をAIが生成し、ドメインエキスパートがレビュー・修正するワークフローは、ゼロから書くよりも効率的ではないでしょうか。
情報設計がもたらすもの
プロファイルは「作って終わり」ではありません。情報設計を明示的に持つことで、開発プロセスの複数の局面で活用できると考えています。
その前に、OpenAPIのような既存のAPI仕様との違いを整理しておきます。OpenAPIはエンドポイントごとの入出力を定義します。GET /products は商品一覧を返す、POST /cart は商品をカートに追加する —— これは本質的に関数のカタログです。個々の関数の引数と戻り値はわかりますが、「商品一覧から商品詳細を見て、カートに入れて、注文する」という一連のフローは表現されません。エンドポイント同士の関係性も、productName と orderProductName が同じ語彙なのかどうかも、OpenAPIの守備範囲の外です。
ALPSはその上位に位置します。語彙を統一的に定義し、状態と遷移でアプリケーション全体の構造を記述します。OpenAPIが「この関数は何を受け取り何を返すか」を定義するのに対し、ALPSは「このアプリケーションは何を扱い、どう振る舞うか」を定義します。前章でALPSからOpenAPIを生成しましたが、逆方向 —— OpenAPIからALPSを生成すること —— はできません。関数リストから情報設計は復元できないからです。
AIへのアプリケーション説明
LLMにアプリケーションの全体像を伝えるとき、ソースコードをそのまま渡すのは非効率です。EC-CUBEの場合、コントローラだけで数万行、Entityやテンプレートを含めれば桁が変わります。一方、ALPSプロファイルは413のディスクリプタでアプリケーション全体の「何があり、何ができるか」を構造化して記述しています。
コード生成、バグ調査、テスト生成など、AIにコンテキストを与える場面でプロファイルは有用です。語彙と遷移が定義されていれば、AIは個別のソースファイルを読む前にドメインの全体構造を把握できます。ただし、プロファイルだけで十分かというとそうではなく、実装の詳細が必要な場面ではソースコードとの併用が前提になります。
オンボーディング
新規参加者が最初に知りたいのは「このアプリケーションは何をするのか」です。状態遷移図を見れば画面フローがわかり、ディスクリプタ一覧を見ればアプリケーションが扱うデータ語彙がわかります。コードを読む前に全体像をつかめることは、特に大規模なコードベースでは価値があるはずです。
EC-CUBEの場合、フロントエンドだけでも商品一覧→商品詳細→カート→注文→マイページという基本フローに加えて、会員登録、パスワードリセット、問い合わせなど複数の独立した画面群があります。これらの関係をコードから読み取るには相当な時間がかかりますが、状態遷移図であれば一目で把握できます。
リファクタリングの指針
情報設計がコードの上位にあれば、「この変更は語彙や遷移に影響するか」を判断できます。DB正規化やクラス分割のような内部実装の変更と、API変更や画面追加のようなインターフェースの変更を区別できるということです。
例えばProductエンティティの内部構造をリファクタリングする場合、ALPSのディスクリプタに変化がなければ、それは「外から見た振る舞いを変えない」変更だと判断できます。逆に、新しいディスクリプタや遷移の追加が必要になるなら、それはインターフェースの変更であり、影響範囲の検討が必要です。
フレームワーク・言語の移行
EC-CUBEは2.x(独自フレームワーク)→ 3.x(Silex)→ 4.x(Symfony)とフレームワークを変えてきました。しかし「商品」「注文」「顧客」の語彙と操作は本質的に変わっていません。フレームワークが変わっても、ユーザーがECサイトに求めることは同じだからです。
情報設計がフレームワークから独立して定義されていれば、移行時に「何を保存し、何を変えるか」の判断基準になります。ALPSのディスクリプタは移行先でも維持すべき仕様であり、ルーティングやDIコンテナの設定は移行先のフレームワークに合わせて変える実装詳細です。もちろん、現時点のプロファイルは4.3のソースコードから逆算したものなので、フレームワーク非依存を完全に達成しているわけではありません。
仕様駆動開発
今回のプロファイルはソースコードからの逆算 —— リバースエンジニアリング —— で生成しました。しかし本来は逆方向、つまり情報設計を先に定義し、そこからコード・API・ドキュメントを派生させるのが理想です。
ALPSプロファイルを「シングルソースオブトゥルース」として、OpenAPI、JSON Schema、テスト仕様を自動生成するワークフローが考えられます。前章で示したOpenAPIへの変換はその一例です。プロファイルを変更すれば派生する成果物もすべて更新される —— そうした開発フローが実現できれば、仕様と実装の乖離を構造的に防げます。ただし、これはまだ構想の段階であり、実際のプロジェクトでの検証はこれからです。
リンク
- EC-CUBE 4.3 ALPS Profile — リポジトリ
- ALPS ドキュメント — 状態遷移図とディスクリプタ一覧
- OpenAPI サンプル — フロントエンドAPI参考仕様
- ALPS 仕様