概要
要約
API設計の経験を通してGraqhQLに対してのイメージが変わったので、
その思考過程をまとめる。
対象読者
- GraphQL学びたい人
- GraphQLのメリットがわからない
- GraphQLアンチの人
- BFFでよくねとか思ってる人
- BFFとGraphQLで迷っている
- なんかよくわからないけどGraphQL学んでる人
免責事項
この記事はあくまで筆者の感想をまとめたもので、試算や検証をしていないので事実と異なることを述べている可能性があります。
なぜアンチだったのか
GraphQLを学ぶ気になれなかった理由は、メリットがわからなかったこれに尽きる。それまでは密結合になるのはマイクロサービス化などが視野に入ってくる段階だと思っていた。そのため、その段階でテストの難しさをデメリットとしてあげる人が多いGraphQLを導入するくらいならBFFを作成した方がいいと思っていた。よっってそれまでは、アプリが複雑化することもないだろうしFEで結合して貰えばいいのではくらいに思っていた。しかしながら立ち上げ初期でも後述する要求の食い違いがすでに存在しうることを実体験として知るにつれて、考えが変化していった。
きっかけ
FEとBEの要求の違いから生じる歪みを感じた体験
フロントエンドとバックエンドが別々のチームで開発されているプロジェクトのAPI定義をするようなった。
これまで画面はテンプレートエンジンでしか書いたことなかったので、初めてRESTで結合するアプリケーションを担当し、以下のような共存し難い要求が存在することに気がついた。
- FrontEndの要求
- 関連するデータはなるべくまとめて欲しい
- これはユーザビリティから起因する、極めて重要な要求だ
- これを無視するとエンジニアよがりな使い手を無視したアプリケーションになってしまう
- 関連するデータはなるべくまとめて欲しい
- BackEndの要求
- データを疎結合にしたい
- APIであってもなるべくデータを疎結合にしたい
- というのも別にIF層だけ連結させて、アプリケーション層やドメイン層を疎結合にするだけでもいいのだが、そうすると技術力がよほど高い集団以外だとかなりの設計コストが嵩むようになる可能性がある
- データを疎結合にしたい
今回の設計ではバックエンドが上記の歪みを受け入れる形で、アプリケーションを実装したのだが、いまでもこれは正しい選択だったのか大いに悩んでいる。
免罪符としてどうするのが良かったのかを、各アプローチのトレードオフを分析しながら考えていく。
歪みを生まないためのアプローチ
自分が思いつく限り、以下のアプローチで両者の要求を共存させることが可能だと考える。
- RestAPIのインターフェース層で吸収する
- GraphQLを導入する
- 自前でBFFを実装する
- クラウドの機能を使用してBFFを立ち上げる
これからそれぞれのアプローチで考えうるトレードオフについて考察しする。
RestAPIのインターフェース層で吸収する
このアプローチでは、バックエンドのリクエストを受けるインターフェース層はデータの結合を許容し、そこから疎結合に実装されたユースケース層へ適切なリクエストを分岐し、その結果を結合してクライアントへレスポンスを返却する手法である。このアプローチでは以下のトレードオフが存在すると考える。
- メリット
- 慣れ親しんだRestAPIを使用することができる
- 追加コストなしで実現できる
- デメリット
- 設計コストの肥大化
- インターフェースの定義とユースケース層以降実装で、データ型の定義が異なるようになり、その部分の設計意図をメンバーに把握してもらうための工数が必要になる
- 工数がどのくらい肥大するかメンバーの習熟度によって異なる
- ファットコントローラーへの懸念
- インターフェース層でハンドリングする処理が出てきてしまうため、ドメイン知識が一部IF層に流出してしまう懸念は拭えない
- またアプリケーションが習熟するにあたり、実装が複雑になる可能性も大いにある
- 設計コストの肥大化
GraphQLを導入する
タイトル通りの実装である。この場合のトレードオフは以下のようになるだろう。
- メリット
- モダンなアーキテクチャを実装する満足感
- 追加コストなしで実現できる
- デメリット
- 学習コスト
- インターフェーステストへの課題
自前でBFFを実装する
こちらもそのまま。この場合のトレードオフは以下のようになるだろう。
- メリット
- 慣れ親しんだRestAPIを使用することができる
- デメリット
- 追加のインフラコストがかかる
- 耐障害性を考えてスケーリングとかすると、結構いきそう(試算はしてない)
- 実装コストが跳ね上がる
- 学習コストも跳ね上がりそう
- 仮にFEで実装・管理する場合、FEの負担が重くなりそう
- 逆だとするとFEは柔軟な仕様変更という恩恵が受けられない
- 追加のインフラコストがかかる
クラウドの機能を使用してBFFを立ち上げる
こちらもそのまま。この場合のトレードオフは以下のようになるだろう。
- メリット
- 慣れ親しんだRestAPIを使用することができる
- デメリット
- 追加コストが発生する
- 自前構築よりはマシ?
- クラウドベンダーへの依存が強まる
- これにより為替の影響が大きくなったり、ベンダーの都合で費用が嵩むリスクは当然増える
- 昨今のIT貿易赤字やら、オンプレ回帰やらのトレンドを鑑みると少し慎重になる気持ちもある
- 追加コストが発生する
まとめ
こうしてみると、やはりGraphQLというのはそこまで悪くない選択肢のように思えてくる。
もちろんプロジェクトの資金状況や、会社ないしビジネスのフェーズや要望によって左右されるだろうが、現状筆者は以下のような判断基準で選定を行うかもしれない(機会と権限があれば)。
- 資金力があるプロジェクト
- クラウドが利用できる
- クラウドの機能を使用してBFFを立ち上げる
- オンプレ
- GraphQLの導入
- クラウドが利用できる
- 技術力があるチームのプロジェクト
- GraphQLの導入
- RestAPIのインターフェース層で吸収する
- クラウドの機能を使用してBFFを立ち上げる
- 普通のプロジェクト
- GraphQLの導入
- そのまま突き進む
- 継続開発なら自前BFFもありかも
色々悩んでいる最中なので網羅性がないのはご容赦いただきたい。
追記
指摘されて改めて調べてみたらGraphQLで完全に実装を切り分けるのは難しそう......
Queryは結合を受け入れて、Commandはきっちり分けるとかが無難なアプローチになりそう