Gaudiy Tech Blog

Gaudiyの技術、開発組織、カルチャーについてお伝えするブログです

システムの変動性の特定とアーキテクチャ設計

f:id:hanahanayaman:20220128221846p:plain

こんにちは。エンタメ領域のDXを推進するブロックチェーンスタートアップ、Gaudiyでエンジニアをしている勝又(@winor30)です。

Gaudiyでは、アイドル、ゲーム、マンガなどの様々なIP(知的財産権を有するコンテンツ)をベースにしたファンコミュニティを提供し、そのコミュニティ上で様々なサービスが利用できるような "スーパーアプリ" のようなプロダクトを開発しています。

このような特性のプロダクトづくりにおいて重要なのは、特定のIPコンテンツに特化させずに、どうやってコミュニティ上のサービスをつくっていくのか? という点です。

そこでGaudiyでは、よりスケーラブルでレバレッジの効いた開発をするため、ソフトウェアの原則を重視しながらも、コラボレーションを通じてプロダクトビジョンを捉えることによって、正しい技術的な意思決定をしていこうという考え方があります。

今回は、上述したような意思決定プロセスを、実際に開発した様々なデジタルアイテムの購入システムを例に説明していこうと思います。事業にレバレッジをかけることができるような拡張性のあるソフトウェア開発の参考になれば嬉しいです。

1. レバレッジの効いた開発に必要なことは?

最も大事なことは、プロダクトビジョンを捉え、将来の拡張性を予想することです。

一般的に、将来の拡張性を予想することはYAGNIの精神に反するため、XP的な考え方からするとアンチパターンのように思われます。しかし、投資的な開発を実現できるとのちの追加実装が楽になり、事業進捗を加速させることができます。

そこでGaudiyでは、エンジニアだけでなく、PdM、BizDev、コミュニティマネージャーなど様々なステークホルダーからプロダクトに関するビジョンや将来の方向性を徹底的にヒアリングし、それらを設計に落とすようにしています。

1-1. ヒアリングの方法

ヒアリングの方法は、できるだけコラボワーク(協働できる作業)を取り入れて、ステークホルダーの考え方やメンタルモデルをつくることに注力しています。このコラボワークは、現在だとストーリーマッピングやDDDによるドメインモデルづくりなどがあります。

(GaudiyのDDDの取り組みについてはこちらの記事が詳しいです。)

techblog.gaudiy.com

このときに様々なことをヒアリングするのですが、最も大事だと考えているのは、プロダクトのWHYと将来性をヒアリングしていくことです。この部分は後述する「カプセル化すべきシステムの変動性」に直結していく部分になるので、どういう変化があるのか? というところを様々なステークホルダーにヒアリングすることが重要です。

また、聞き方として気をつけていることとしては、以下の点があります。

  1. ステークホルダーが使った単語・言葉をそのまま使う
  2. 具体例を聞いたあとに抽象的な話を聞く

まず1点目については、ステークホルダーがイメージするモデルを、聞き手のバイアスなしでそのまま引き出すためです。相手が使った単語・言葉を聞き手が言い換えてしまうと少し誘導してしまう形になり、本来のメンタルモデルを汚してしまう恐れがあります。この考え方は「クリーン・ランゲージ」という書籍にある考え方で、どうやって相手のメンタルモデルを100%引き出し、バイアスなしで理解できるか? という方法になります。

この手法はコンサルタントやUXリサーチャーなどがよく使っているのですが、エンジニアのモデリングも本質的には同じだと考えており、相手のモデルを理解し、それをアーキテクトしていくことが良いシステムを作っていく上で大切だと考えています。ただ個人的にはバイアスなしにヒアリングを進めるのはかなり難しく、「こういうシステムになるだろうな…」と予想しながらヒアリングをしてしまうなど、認識の誤差が埋まらないケースなどもありました。

次に、具体例を聞いたあとに抽象的な話を聞くこともメンタルモデルの理解を深めるためのひとつの手段です。最初に同じように認知できやすい実際のケースを聞くことによって、その後の抽象的な概念を具体例と照らし合わせることにより、認識の誤差を減らしていくことができます。

1-2. カプセル化すべきシステムの変動性の導出

また、前述のヒアリングを通して「システムの変動性」を見つけることが、プロダクトにレバレッジを効かせるためには不可欠です。

この変動性とは、Righting SoftwareBuilding Microservices, 2nd Editionなどに書かれている、ビジネスドメインの境界を見つける手法の一つになります。

変動性をソフトウェアに適応するということは、変更される可能性がある領域を明確にし、その部分をサービスやシステムとしてカプセル化することで、その変化が他のシステムに影響を与えないようにすることを指します。

サービスの境界を見つける手法としては、DDDを利用して、Bounded Contextが境界になるやり方も存在するとは思います。ですが、変動性による分解を利用する方が、どういった変動領域から他のシステムを守りたいのか?という視点で境界を定められるので、より柔軟なビジネスドメインの境界を見つけることができる印象をもっています。

また個人的には、SOLIDの単一責任の原則と変動性のモチベーションがかなり近いと考えており、分解の手法としてはかなり有用なものだと考えています。

この変動性領域は「あとから変更できる」という意味合いではなく、「将来的にどういう変化をする可能性が実際にあるのか?」という点が大事です。そのために、PdMやコミュニティマネージャーにプロダクトビジョンをヒアリングしながら、「将来どういうことが行われるのか?」「この機能に対してどんなイメージをもっているのか?」などをエンジニアのバイアスなしにヒアリングしていき、どのような変動性があるのかを見極めていきます。

2. 様々なデジタルアイテムの購入に関する適用例

上記で説明したような変動性の導出を実際の機能開発で行ったので、そのプロセスや実際にやったことを説明します。

2-1. ヒアリングによる変動性の導出と技術的意思決定

f:id:hanahanayaman:20220130145151j:plain
デジタルアイテムの購入イメージ

今回開発した機能としては、様々なデジタルアイテムをクレジットカードで購入できる機能です。

この様々なアイテムとは、具体的に下記3つを購入できるようになっています。

  1. コミュニティ内で閲覧できるライブ配信のデジタルチケット
  2. コミュニティ内でデジタルアイテムがもらえるガチャを引くことができるガチャチケット
  3. コミュニティと連携している(Gaudiyが運営していない)ソシャゲのアイテム

これらのアイテムを、Gaudiyが提供しているコミュニティ内から同じようなフローで購入できるような機能を開発しました。

このプロジェクトで実際にステークホルダーに対するヒアリングを実施した結果、「購入条件の変動性」と「購入商品の変動性」が存在することがわかったため、この部分をカプセル化するようなモデリングの意思決定を行いました。

購入条件の変動性としては、コミュニティで販売するにあたって、コミュニティや外部アプリでの条件(ex. コミュニティレベルや外部アプリのアカウントを持っているか?など)がありました。この条件が増えていくことは、将来的にコミュニティで利用できる新しいエンタメの購買体験を作るというビジョンを持っていたため、必要があると考えました。

また購入アイテムの変動性は、販売するアイテムがコミュニティ内部のアイテムだけでなく、同一IPのソシャゲやECなどコミュニティ外のアイテムを購入できることもビジョンとしてあるため、アイテムが増えるという変動性から他のシステムを守りたいと考え、必要だと考えました。

2-2. Sagaパターン x Orchestrationで結果整合性を担保

f:id:hanahanayaman:20220128153040p:plain
Sagaパターンの正常ケースと異常ケース

変動性を導出した上で、今回は機能の特性上、どうやってアプリケーションとの整合性を担保するかを考慮する必要がありました。

一般的には、可能であれば整合性はDBのトランザクション等を利用してアトミックに行うのがよいとされています。

しかし、アイテムが外部のサービスの商品であったり、そもそも決済代行のAPIが外部のものを利用したりしていたため、今回は結果整合性を担保するような方針でシステムを作っていくことにしました。

そのため、マイクロサービスでの結果整合性を担保させるのに有用なパターンである、Sagaパターンを利用しました。結果整合性を担保したいワークフロー的な処理のどこかで失敗した場合は、全てのデータを元に戻すような補償トランザクションを送ることによって、結果整合性の担保を実現しています。

また、Sagaパターンを利用しつつ、OrchestrationとCoreographyの選択としてはOrchestrationを採用しています。

この意図としては、全体的な購入のワークフローにおいて、失敗したときに、直感的にロールバックを実行しやすく、シンプルな構成になりやすいためです。Coreographyの選択も社内で議論はしたのですが、最終的にピタゴラスイッチ的になり複雑化する懸念があったので、シンプルなアーキテクチャパターンの方を選択しました。

3. 実際の構成

3-1. アーキテクチャ

f:id:tkatsumat:20220131111529p:plain
実際のアーキテクチャ

基本的にupstream serviceとしてPaymentServiceがあり、downstream serviceとしてCheckService、GiftService、決済代行の外部APIが存在するようなアーキテクチャになっています。

ステータスの状態に関しても、どこで失敗したのかに関しては観測可能な状態になっているため、仮に結果整合性が担保できなかった場合でも、どこまでやり直せば良いのかがわかる仕組みになっています。

また、各サービスは購入のメインユースケース以外にも、クレカの登録や商品情報の表示、購入条件の表示などのユースケースに対しても利用されています。

3-2. ストラテジーパターンの利用

購入アイテムや購入条件の変動性によってチェックロジックが走る部分に関しては、ストラテジーパターンを利用し、インターフェースは共通にしながらも内部実装を種類ごとに分けていきました。

 

また、ソフトウェアの構成的にもストラテジーの選択と実行を分けて、より疎結合な設計にしています。

 

ストラテジーパターンを利用した意図としては、購入アイテムや購入条件の変動性をカプセル化したとしても、変動性による影響がソフトウェア内部で発生はするので、その影響を最小限に留めたかったためです。

この設計パターンを利用したおかげで、基本的には新しいものが追加された場合は、その実装クラスを選択するロジックとその実装クラスの内部ロジックを実装するだけでよくなり、より柔軟なソフトウェアアーキテクチャになりました。

4. まとめ

今回は実際にGaudiyで開発したデジタルアイテム購入の機能に関して、どんなところを気をつけながら事業のレバレッジを仕込めるようなものにしていったのかという点に関して説明しました。

事業を推進させるためのエンジニアの役割として、ステークホルダーのメンタルモデルを正しく探り、ソフトウェアの原則を正しく適用することによってレバレッジのあるアーキテクチャを作っていくことが、非常に重要だと個人的には考えています。

ただし、こういった取り組みはまだまだ試行錯誤している部分も正直あるので、こういった不確実な領域でアーキテクトをしていきつつプロダクトに影響を与えたい方がいれば、ぜひ色々議論していき、よりよいプロセスや原則を探っていきたいです!

meety.net

Gaudiyの技術選定とその思想については、以下の記事をご参考ください。

techblog.gaudiy.com