SaaSのエレガントな連携とは

SaaSにおけるエレガントな連携ってなんぞってのを言語化していく(実はSaaSだけじゃなくて連携全般)

Screen Shot 2020-10-14 at 0.45.16.png (78.4 kB)

一言でいうと、疎結合であればあるほどエレガントで、依存性の方向が単方向だとエレガントである。

最近Looker連携を実装して、「これはエレガント!」と感心したのでLookerを例にしていく。

Lookerが提供するエレガントな連携

疎結合ってなんぞ?

疎結合ってのは、やりたいことをやるために知るべき知識が少ないということである。

Lookerでいうと、「GroupAのユーザーHogeAです!ダッシュボードBを頂戴!!」しか、ドメインでは意識していない。 ドメインの誰が見たいとリクエストしているか。と、ダッシュボードがA,B,C複数種類あるよ。くらいの知識しか知らないのである。 「ダッシュボードを見たいユーザーがLooker側に存在するユーザーなのか」 とかはすべての層で意識せずに済んでいる。(すごない?)

依存性の方向が単方向ってなんぞ?

「GroupAのユーザーHogeAです!ダッシュボードB頂戴!!」で結果が得られるのは、 連携元システム -> Lookerという依存性の方向になる。(連携元システムはダッシュボードを得るためにLookerに依存している) これだけで済めば依存性の方向は単方向である。

ダッシュボードを得るために「Lookerはダッシュボードを渡すために連携元システムにユーザーの生成を求めているという」条件があれば Looker -> 連携元システム の方向でも依存し、双方向の依存になる。

どうやってやってるの?

これは、ユーザーの作成処理をLooker側がAPI実行時にアトミックに行ってくれているから実現している。

「ユーザーHogeAです。ダッシュボードB頂戴」というリクエストをLooker側に送ると、 Lookerは「あー、はいはい。HogeAさんね。そんなやついないなぁ〜?作っといたわ。はい、ダッシュボードBをどうぞ。」 という感じで暗黙的にユーザー作成を行ってくれるのでLooker側の状態をこちらが意識する必要がまったくない。

(だるまに教えてもらったんだけど、こういうのをJITプロビジョニングというらしい。知見。コレのおかげでドメイン層はダッシュボードの種類しか意識せず疎結合に出来てるし、依存の方向も単方向にできている)

ユーザー作成時に属性としてgroup_id等を渡しておけば、ダッシュボードに露出するデータは渡したgroup_idに紐づくようにできる。

権限処理すらこなしてしまうのである。実にエレガント。

逆にエレガントじゃない連携って?

例えば、ユーザーが存在しないと、「User not found!」と返してきて終わりのサービスも割とある。(ユーザーは料金体系に紐付いたりするので例として微妙かもだが)

その結果をもってユーザーを作る処理を入れないといけず、連携先の状態を意識しないといけないし、依存は双方向になってしまう。

もし依存が双方向なら、LookerEmbedUserみたいなドメインモデルとRepositoryを用意して、findById->(存在なかったらEmbedUserを作成) ->埋め込みUrlを取得 みたいな感じで書きたくなってしまう。

こうして結合度が上がっていき、エレガントではなくなる。

エレガントじゃない連携に対抗するには

個人的にはこの程度でドメインに顔は出したくないので、委譲処理内でユーザー存在確認->作成のようなretry処理を入れてしまい、委譲処理の一部として隠蔽し、ドメインからは追い出す。

自分が大規模システム作る時に組むアーキテクチャは委譲処理を書く場所をドメインとは別に設けていて、そこで頑張ることで単方向にできるようにしている。

エレガントさ

Lookerのすごいところはこういう層で頑張らなくても普通に単方向にできる点。

厳密にいうと連携というのは連携元、連携先双方に合意(tokenやユーザー,権限)がないと成り立たない。

Lookerのエレガントさを作っているのは以下の点。

  • 先にエンジニアが投入しておく設定(tokenやgroup_idによる権限で見れる範囲等)と、リクエストベースで自動で登録される設定(ユーザーやユーザー属性)の分離がめちゃくちゃうまい
  • JITプロビジョニングを想定した料金体系になっている

エンジニアが投入しておく設定で大まかな合意(システムtokenや権限)を完了し、システム側で細かい合意(ユーザー作成やそのユーザーと権限の紐付け等)をアトミックにやることで単方向の依存と疎結合な連携を可能にしている。

エレガントでない定義

以下を満たすものではないかと考えている。

  • 連携元に不必要な依存を要求し、双方向の依存を作る
  • 連携元に不必要なオブジェクトのライフサイクルを管理するよう要求し、連携元のドメインに侵食する

これらは連携元システムのアーキテクチャである程度対応可能だが、素直に書くとひどい密結合を生み出してしまう。 (サービスの料金体系の都合でJITプロビジョニングをできないパターンは普通にあるので、それをイケていないと言うつもりはないが、料金体系に関係ない部分でこのやり方が適用できる箇所はたくさんあるはず。)

SaaS連携にも設計の原則は適用できる

  • SaaSは、連携元システムから捉えると、マイクロサービス1要素と捉えることができる。(SaaS連携=マイクロサービス間連携)
  • 疎結合とか依存の方向が単方向なんてものは、設計界隈では太古の昔から存在するセオリー。メリットも自明で、それを適用しないのはもったいなさすぎる
  • セキュリティ要件が違うので、内部システムほど気楽に連携できるものではないので考慮すべきポイントは多いが、Lookerのようにエレガントな連携は実現できる。
  • 結合が強すぎると、それは分散モノリスであり、マイクロサービスでなくなってしまう。
  • 連携元システムに不必要に分散モノリスとしての振る舞いを求めるSaaSやマイクロサービスはイケていない。
    • 同じように、不必要に密結合にしてしまう連携元システムもイケていない。