07
第 7 章

BFF の肥大化と責務境界

この章で学ぶこと
1 BFF にビジネスロジックが入り込む Fat BFF の問題
2 BFF の責務を集約・整形・認証仲介に限定する方針
3 BFF 乱立によるロジック重複の問題
4 体験の違いで BFF を分割・統合する判断基準
図解

環境の構成

BFF が5つのバックエンド APIを集約する構成

環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ
要点

本講座で扱った BFF の責務

集約複数のバックエンド APIのレスポンスを 1 つにまとめる
整形フロントエンドが表示しやすい形にデータを変換する
セッション管理認証状態を保持し、トークンをブラウザに露出させずに扱う
縮退バックエンド APIの障害時に機能を段階的に落とし、主要機能を維持する

これらはすべてフロントエンドを成立させるための技術的関心事であり、業務のルールそのものではない

環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ
要点

Fat BFF とは

Fat BFFBFF に価格計算・在庫判定などの業務処理(ビジネスロジック)が入り込んで肥大化した状態
BFF の本来の責務を超えている
技術的関心事(本来の責務)
集約・整形・セッション管理・縮退
業務のルール(本来はバックエンドの責務)
価格計算・在庫判定などのビジネスロジック

この章では Fat BFF がなぜ生まれるのか、何が問題なのかを整理する

環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ
解説

Fat BFF が生まれる経緯

BFF はデータを手元に持つ
バックエンド APIのレスポンスがすべて揃っているため「ここで1行加えれば動く」という判断になりやすい
要件追加のたびに条件分岐が増える
価格計算、在庫判定、権限チェックが順番に追加されていく
バックエンド API への依頼より BFF 側で書くほうが速い
短期的な対応速度がロジック混入を加速させる
環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ
コード

Fat BFF のコード

ビジネスロジックが混在した BFF — 価格計算・在庫判定・権限チェックが集約処理の中に埋め込まれている

anti-pattern/src/routes/product.js
📂 お手元のエディタでお開きください
47 行
環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ
図解

Fat BFF の構造

BFF のルートハンドラにビジネスロジックが混在した状態

環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ
解説

なぜバックエンド APIが担うべきか

ドメイン駆動設計の考え方
マイクロサービスは「境界づけられたコンテキスト」というドメインの境界ごとに分割されている
各サービスが自分のドメインのルールを持つ
商品サービスは価格計算、在庫サービスは在庫判定という、それぞれのドメインのビジネスルールを所有する
ドメインの境界を越えてロジックを書くべきではない
BFF が価格計算を行うことは、商品ドメインのルールを BFF に複製することであり、ドメインの境界を崩す
環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ
注意

Fat BFF の問題点

二重管理
同じ判断が BFF とバックエンド APIの両方に存在し、片方だけ修正すると整合性が崩れる
ビジネスルール変更が BFF に波及する
価格体系の変更のたびに BFF も修正・再デプロイが必要になる
環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ
図解

Fat BFF と正しい BFF の対比

各責務を誰が担うかの対比

環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ
解説

BFF 乱立の問題点

「1フロントエンド = 1 BFF」の機械的適用によってBFFが乱立
クライアントの種類が増えるたびに BFF を追加する判断になりがち
たとえば、、Desktop Web、Mobile Web、iOS、Android、Admin が
それぞれ専用の BFF を持つ、のようなイメージ
メンテナンス性の著しい低下
各 BFF が同じバックエンド APIを呼び出して同じ処理を行う
同じ集約ロジックや変換ロジックの並立
環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ
コード

重複した集約ロジック

Desktop Web BFF と iOS BFF で集約ロジックがほぼ同一

anti-pattern/src/web-bff.js / ios-bff.js
// web-bff.js(Desktop Web BFF)const [user, orders, notifications] = await Promise.all([  fetch(`${USER_SERVICE}/users/${userId}`),  fetch(`${ORDER_SERVICE}/orders?userId=${userId}&limit=10`),  fetch(`${NOTIFICATION_SERVICE}/notifications?userId=${userId}`),]); // ios-bff.js(iOS BFF)const [user, orders, notifications] = await Promise.all([  fetch(`${USER_SERVICE}/users/${userId}`),  fetch(`${ORDER_SERVICE}/orders?userId=${userId}&limit=5`),  fetch(`${NOTIFICATION_SERVICE}/notifications?userId=${userId}`),]);
環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ
図解

BFF 乱立の構成

5つの BFF が同じバックエンド APIを呼び出す乱立構成

環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ
解説

体験の違いで統合する

Desktop Web + Mobile Web → Web BFF
ブラウザで同じ Web アプリを表示する体験は共通
iOS + Android → Mobile BFF
ネイティブモバイルアプリとして提供する体験は共通
Admin → Admin BFF
管理画面は表示範囲・操作権限が異なるため独立を維持
環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ
図解

統合後の構成

5 BFF から 3 BFF への統合

環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ
まとめ

この章のまとめ

Fat BFF は、BFF にビジネスロジックが入り込んで肥大化した状態であり、二重管理とビジネスルール変更の波及を招く
BFF の責務は集約・整形・認証仲介に限定し、計算・判定・状態変更はバックエンド APIに委ねる
責務境界とは、BFF が担うべき処理と担うべきでない処理の境界線のこと
BFF の分割は「1つの体験 = 1つの BFF」を基準にし、同一体験のクライアントは BFF を共有する
次章: BFF を導入するか・しないか・切り出すかの判断基準
環境準備
Fat BFF
責務境界
BFF 乱立
体験ごとの統合
まとめ