UI Boundary Architecture
UI Boundary Architecture は、UIを見た目の大きさではなく、責務と状態所有の境界によって分割する設計手法です。
この手法が解決する問題
Section titled “この手法が解決する問題”宣言的UIフレームワークで画面を作っていると、次のような状況になりがちです。
分割の基準が「大きさ」になる。 「これは大きいから親コンポーネント」「これは小さいから子コンポーネント」という判断を続けると、名前は増えるのに、それぞれが何に責任を持つのかは決まりません。結果として、すべての要素を「コンポーネント」という同じ言葉で呼ぶことになり、設計の議論ができなくなります。
状態の置き場所が、分割の基準と別々に決まる。 「この値は2箇所で使うから親へ上げる」という判断を繰り返すと、状態は自然と画面の最上位へ集まります。最上位に集まった状態は、そこから下へ props として順に渡され、途中のコンポーネントは自分では使わない値を中継するだけになります。
どこを直すと何が壊れるか分からない。 状態が最上位にあると、その値を読んでいる場所は画面のどこにでもありえます。1つ変えるたびに、確認すべき範囲が画面全体へ広がります。スパゲッティコードとして感じられるのは、多くの場合この部分です。
どこまでが再描画されるのかも分からない。 確認すべき範囲が広いことと、再描画が及ぶ範囲が広いことは、同じ原因から起きています。投稿欄に1文字入力しただけで、無関係なタイムラインの全投稿まで描き直される、という状態です。
Atomic Design を当てはめようとしたが、決められない。 部品が重複してきたので調べてみたものの、目の前の要素が Atoms・Molecules・Organisms のどれに当たるか決められない。ページ固有のUIをどこへ置くかも書かれていない。理論と実装が離れているように感じる。
はじめの4つは、どれも個々の判断としては正しく見えます。問題は、判断の基準が「大きさ」しかないことです。
こうなったページを、この文書では God Page と呼びます。状態が絡み合い、どの状態が誰に使われているのかを追えなくなったページのことです。スパゲッティコードと呼ばれる状態のうち、UIの状態が原因になっているものだと考えてください。手元にそういうページがあるなら、ほぐす手順が 第6章 適用のしかた にあります(用語は 第1章 が前提です)。
最後の1つ、Atomic Design が当てはまらないように見える理由は 第5章 既存の設計手法との比較 で扱います。先に結論を書くと、Atomic Design は悩みの半分にしか答えていません。 部品をどう分類し、どう揃えるかには答えます。答えていないのは、ページ固有のUIをどこに置くかと、状態をどこに置くかです。
UI Boundary Architecture は、大きさの代わりに「何を分けているのか」を基準に置きます。
基本となる単位は次の5つです。
Scaffold└─ Bridge └─ Island └─ Component └─ Part| 単位 | 境界 | 主な責務 |
|---|---|---|
| Scaffold | Screen Boundary | 画面構造と画面状態 |
| Bridge | Coordination Boundary | 複数の Island の協調 |
| Island | Feature Boundary | 機能とその状態 |
| Component | Interaction Boundary | 操作と振る舞い |
| Part | Presentation Boundary | 表現 |
この分類が答えようとしているのは、次の2つの問いです。
- この責務はどこまでか。
- この状態を誰が所有するか。
いちばん迷いやすい Component と Part の見分け方だけ、先に触れておきます。自分で状態を持つなら Component、持たないなら Part です。Button は押されているかどうかを持つので Component、Card は何も持たないので Part です。詳しくは 第1章 で扱います。
なぜ5つなのか
Section titled “なぜ5つなのか”5つという数は、先に決めて当てはめたものではありません。UIが引き受けている責務が、次の5種類に分かれるからです。
| 責務の種類 | 対応する単位 |
|---|---|
| この画面をどう成立させるか | Scaffold |
| 機能同士がどう連動するか | Bridge |
| ひとつの機能が何を管理するか | Island |
| ユーザーの操作をどう解釈するか | Component |
| 受け取った情報をどう見せるか | Part |
このうち Bridge だけは、他の設計手法にほとんど対応するものがありません。含む・含まれるの関係では表せない「機能同士の連動」を、独立した単位として扱っているためです(→ 第5章 既存の設計手法との比較)。
大きさの階層ではない
Section titled “大きさの階層ではない”この並びは、UIのサイズや複雑さを表すものではありません。
上の図で Scaffold が最上位にあるのは、含む・含まれるの典型的な関係を示すためです。Scaffold が常に大きく Part が常に小さい、という意味ではありません。
軸と凡例と目盛りを含む大きなグラフが Part であることも、画面の隅に収まる小さな通知センターが Island であることもあります。
5つすべてを使う必要はない
Section titled “5つすべてを使う必要はない”入れ子の図は、5つすべてを必ず配置するという意味ではありません。必要な境界だけを引きます。
たとえば設定画面のように、Island 同士が何も共有していない画面では Bridge を作りません。
SettingsScaffold├─ AccountIsland└─ AppearanceIslandアカウント設定と外観設定は、それぞれ独立して自分の状態を持ちます。共有する状態がないので、協調させる境界も要りません。値を1つも持たない Bridge を挟むと、追う層が1つ増えるだけです。
同じように、Island が1つしかない画面もあります。新しく作る画面は、たいてい Island 1つから始まります(→ 第6章 適用のしかた)。
たとえば、よくあるSNSのタイムライン画面は、次のように分割できます。
TimelineScaffold├─ ComposerIsland│├─ PostSelectionBridge│ ├─ TimelineIsland│ │ ├─ FeedTabs│ │ └─ PostCard│ ││ └─ ThreadIsland│ ├─ PostCard│ └─ ReplyList│└─ TrendsIslandTimelineScaffold は画面全体を成立させます。ナビゲーション、中央のタイムライン、右側の欄を画面上のどこに置くかを決めます。
4つの Island は、それぞれ独立した機能と状態を持ちます。
Island |
役割 | 持つ状態の例 |
|---|---|---|
ComposerIsland |
投稿を書く | 下書きの本文、添付画像 |
TimelineIsland |
投稿を並べる | スクロール位置、未読の新着件数 |
ThreadIsland |
1件の投稿とその返信を見せる | 返信を全件表示しているか |
TrendsIsland |
いま話題になっているものを出す | — |
これらの状態は、互いの Island からは見えません。
一方、「いま開いている投稿はどれか」は、タイムラインとスレッドの両方が必要とします。タイムラインはその投稿を強調するために、スレッドはどの投稿を展開するかを決めるために使います。
この値をどちらか一方の Island が持つと、もう一方はその Island に依存します。そこで PostSelectionBridge が所有します。
PostSelectionBridge は画面には現れません。持っているのは「この2つの Island は、開いている投稿を共有している」という関係だけです。
PostCard が2箇所に現れているのは、同じ Component をタイムラインとスレッドの両方が使っているからです。分類は要素そのものの性質で決まり、どこに置かれるかは問いません。
向かないケース
Section titled “向かないケース”この手法が効果を出すのは、1つの画面に独立した機能が複数あるときです。
次のような画面には持ち込まなくて構いません。
- 機能が1つしかない画面 — ログインフォーム、確認ダイアログのようなページ。
Islandが1つあるだけなので、Bridgeも、Scaffoldによる配置の判断も発生しません - 状態を持たない画面 — 静的な紹介ページ、規約の表示。所有する状態がないため、状態所有の判断そのものが不要です
これらの画面に5つの単位を当てはめると、Island を1つだけ抱えた Scaffold という、名前だけの構造ができます。分割の判断が要らないところに分割の語彙を持ち込んでも、覚える名前が増えるだけです。
| 章 | 内容 |
|---|---|
| 第1章 5つの境界 | 5つの単位それぞれの定義、判定基準、よくある誤判定 |
| 第2章 状態所有 | 状態をどの単位が所有するかの決め方、所有者を移す手順 |
| 第3章 論理構造と描画構造 | 責務の構造と、画面上の見え方が一致しないということ |
| 第4章 レスポンシブ設計 | 画面サイズによる変化を、どの単位が引き受けるか |
| 第5章 既存の設計手法との比較 | Atomic Design、Islands Architecture との違いと併用 |
| 第6章 適用のしかた | 既存コードへの適用と、新規設計の進め方 |
| 第7章 ディレクトリ構成と共有 | ページ固有のUIをどこに置くか、いつ共有へ移すか |
| 第8章 分類に迷ったとき | 迷ったときの判断手順 |
第1章は以降すべての前提です。第2章から第4章は互いに独立しているので、必要なものから読めます。
実装時に手元へ置く規則だけを抜き出した RULES.md があります。判定手順、状態の置き場所、命名、ディレクトリ、禁止事項だけを収めた版で、背景と根拠は含みません。
AI エージェントに UI を実装させる場合は、この圧縮版をプロジェクトの CLAUDE.md や AGENTS.md へ貼り付けてください。
読む順序の目安
Section titled “読む順序の目安”| 目的 | 順序 |
|---|---|
| ひととおり理解したい | 第1章から順に |
| Atomic Design がうまく当てはまらなかった | 第5章 → 第1章 → 第7章 |
| ページ固有のUIの置き場所と、再利用の線引きを決めたい | 第1章 → 第7章 |
| 手元のコードをほぐしたい | 第1章 → 第6章 |
| 判断基準だけ確認したい | 第8章のみ |
用語について
Section titled “用語について”この文書では、次のように書き分けます。
ScaffoldBridgeIslandComponentPart— この手法における5つの単位。日本語の文中でも英字で書きます。- 「コンポーネント」 — フレームワークにおける一般的な構成要素。カタカナで書きます。
Component(第4の単位)と「コンポーネント」(一般語)は別のものです。すべての Island も Part も、実装上はフレームワークのコンポーネントとして書かれます。
また、画面とページも区別します。
- 画面 —
Scaffoldが成立させる表示単位 - ページ — ルーティングとディレクトリ配置の単位
原則として、1つのページに1つの Scaffold が対応します。