新領域への挑戦に向けて。ROXX 共通基盤チームの役割とは
こんにちは。ROXX共通基盤チームのエンジニア、夕暮おこはこと、松井 幸太(Kota Matsui)です。
共通基盤チームでは一緒に働いてくれるメンバーを絶賛募集中です。しかしながら、チーム体制や立ち位置が横断的なため、このnoteでは、共通基盤チームの基本コンセプトや詳細な実務内容・技術スタックなどを丁寧に紹介させていただければと思います。
私たちROXXは、スタートアップのフェーズを終え、巨大な組織へと成長し続けています。目指すのは、スタートアップの速度を維持したままスケールしていく組織像。組織が巨大化していく今だからこそ、私たちは最新のエンジニア組織論をキャッチアップし、我々が将来着地すべき理想形を創造していく必要があります。
私たちが目指しているものは、恐らく殆どの方にとって未知の領域になると考えています。採用に当たっては、このnoteに挙げるような技術の実務経験があることがマストだとは思っていません。将来の開発組織像へのビジョン・価値観を共有でき、そのうえで実践に至れる方を求めています。
このnoteを通して、ここに書かれているような新しい領域への挑戦に、前向きな姿勢で取り組める仲間を増やしていくきっかけになればと思います。
共通基盤チームとは
現在ROXXでは、「Zキャリア プラットフォーム」「back check」の2つのサービスに加えて、新規サービスを立ち上げているフェーズになります。
このような局面において、下記の理由から、新たにチームを切り出すことにしました。
共通で利用できる機能をあらかじめ提供することで、新規サービスでの再開発工数の発生を防ぐ
サービスを横断した統合アーキテクチャを設計し、各々のサービスが再利用性を高めながら密結合になることを防ぐ
各サービスのコアドメインに携わるアジャイルチームが顧客価値創出に専念できるよう、サブドメインを外部へと切り出す
対外的には分かりやすいように共通基盤チームと説明していますが、特に3項目の部分があるため、私たちは自分たちのことをMisc(Miscellaneous:その他・雑多な)チームと自称しています。将来的な話をすれば、共通基盤チームは現在のMiscチームの中の一部門ということになっていくことになります。
Miscチームの扱う領域は広範にわたっています。これを一つのシステム、一つのコンテキストにまとめ上げようとすれば、システムは必然的に巨大化・複雑化してしまいます。
そのため、私たちはチーム編成にあたり、下記の3つの要素を重要視しています。
クロスファンクショナルなメンバーで構成された小さなアジャイルチーム(最大で8人程度)が、可能な限り小さなスコープで自律的に価値創出できるようなスクワッド開発(いわゆるSportifyモデル)を指向する
ビジネスの実態とシステム設計を整合させ、また、ビジネス側にもシステマティックなビジネスモデルを要求する戦略的ドメイン駆動設計を指向する
戦略的ドメイン駆動設計によってもたらされた境界付けられたコンテキストに沿って各コンテキストの責務とインターフェイスを明確化し、コンシューマ駆動契約をはじめとするマイクロサービスアーキテクチャの手法を用い独立デプロイ性を維持する
スクワッド開発
私は共通基盤チームとしてスピンアウトする前、Zキャリア プラットフォームのエンジニアとしてスクラム開発を行っていました。
そこで学んだことがいくつかあります。
チームの人数が増えても開発効率は頭打ちになり、バックログが肥大化するとスクラムイベントにかかる時間も肥大化する
単一のシステム・単一のコンテキストの中でチームだけ分割しても状況はあまり改善しない
ビジネスサイドのステークホルダーにとって、殆どの場合関心は限定されている
スクラム開発は本質的に、チーム一丸となって一つのゴールにたどり着くためのフレームワークだと思います。そのため、人数が増えるとチーム内で認識を揃えるコストが増えていきます。また、増えた人数にあわせてタスクも増やす必要があるため、バックログが肥大化します。Zキャリア プラットフォームでは最大12人のエンジニアがいたことがありますが、バックログの整理だけで一日が終わってしまう、といったこともありました。
対策としてチームを分割をしましたが、お互いに扱っている機能同士がコンフリクトすることが多発し、結局認識を揃えるコストという面では悪化する一方でした。
これらの問題を解決し、小規模なアジャイルチームの強みを維持したままスケールさせていく手法として注目しているのがスクワッド開発です。
スクワッドとは、職能横断で自律した、概ね8人以下のメンバーで構成されたチームのことです。組織をスケールさせるには一つのスクワッドを大きくするのではなく、スクワッドの数を増やすことで対応します。複数の似たミッションを持ったスクワッドの集合をトライブと呼びます。
スクワッドごとのバックログの中でのみタスクの優先度付けがなされ、経営側は各トライブにどれくらいのスクワッドを割り当てるかによって事業レベルでの優先度をつけます。
何も考えずにただスクワッドを形式的に適用するだけではただチームを分割するのと状況は変わりません。重要なことは、スクワッドが職能横断的で自律していることです。スクワッドはスクワッドごとにPOを持ち、エンジニアだけでなくビジネスメンバーも含み、ステークホルダーもスクワッドの中に含まれます。つまり、各スクワッドの扱う領域は1人のステークホルダーのビジネス領域に閉じていることが望ましいです。
各スクワッドが自律するのに必要なのは、明確な責任境界、すなわち境界付けられたコンテキストです。責任境界が不明瞭なままでは自律的なチームは生まれません。また、各スクワッドは各々の意思でリリースをコントロールできる必要があります。従って、インフラレベルでどう分離されているかはともかく、各スクワッドが独立デプロイ性を持ったシステムを構築する必要があります。
前者の責任境界を明確化するのに必要なのが戦略的ドメイン駆動設計であり、後者を実現する方法の一つがマイクロサービスアーキテクチャです。
戦略的ドメイン駆動設計により会社全体のビジネスドメインをモデル化し、それによって生じたコンテキスト境界を実現するためのアーキテクチャを、インフラレベルからサービス間プロトコルまでに渡って技術提供するのが、Miscチームのミッションの一つになります。
スクワッド開発への段階的移行
現実問題として、Miscチームはまだ人数が少なく、フルサイズでスクワッド開発体制を構成するにはエンジニアの人数が不足しています。
しかしROXXの会社規模は急速に成長をし続けており、必要なタスクの量も今後増加していくことは確実ですし、実際、エンジニアリソースさえあれば進められるという状態になっているタスクもたくさんあります。
そこで、近い将来フルサイズのスクワッド開発体制に移行できるようにしつつ、現在のタスク量に適切なエンジニアをアサインできるよう、Miscチームでは一時的にチャプター内兼業型のスクワッドを構成しています。
チャプターとはスクワッド開発の用語で、各スクワッドを横断した専門職のグループです。
当面はチャプターに属するエンジニアを各々のスクワッドに1/3人月のように兼業させて割り当てておき、エンジニアの増員に合わせて各々のエンジニアが兼業するスクワッドの数を減らしていき、最終的には各々のエンジニアが一つのスクワッドに専念できるような状態を目指していきます。
このnoteでは、Miscチームの扱っているビジネス領域・技術スタックをかなりの数挙げていくことになりますが、上記のような背景がありますので、すべての領域を担当できるエンジニアを探しているわけではありません。まずは新しく入ってくるメンバーが希望する領域を担当してもらいつつ、あまりに偏りが大きい場合には調整したり、何かあった時に他の領域の作業を手伝ってもらったり、といった動きを想定しています。
担当領域
Miscチームには各サービスのサブドメインを独立させていくというミッションもあるので、取り扱う領域は常に発見的に拡大していきます。
記事執筆時点で担当している領域としては下記のようなものがあります。
認証基盤
現行のモノリス上で管理されている認証情報をサブドメインに切り出して独立したサービスとし、SSO(Single Sign On)を実現します。
セッション管理を行うSSOゲートウェイを各サービスから分離し、各サービスはJWT(JSON Web Token)上のプリンシパルから適切な権限を確認して認可処理を行います。
現在技術検証が完了し、本番環境の移行作業を準備中です。
データ分析基盤
ROXXではBigQuery上にデータ分析基盤を展開しています。各サービスから提供されたデータレイクをデータ基盤上で統合し、分析に利用可能なデータウェアハウスとデータマートを提供しています。
dbt(data build tool)でメタデータ管理することでデータの流れを把握し、事業企画室と相談しながら集計値の定義などを整えています。
また、データ分析に不慣れなビジネスメンバーのために、分析手法の提供やレポート作成の補助なども行っています。
dbt環境はPRマージ前にCIで実際にデータを作って検証する環境を提供しており、品質を維持しながら高速にデータウェアハウス・データマートを追加していけるようにしてあります。また、逆にデータ基盤上のビルド時に不整合なデータを見つけてシステム側の不具合を発見したりすることもあります。
データウェアハウスはDDDの集約に基づいたデータ継承ルールを策定しており、複数のテーブルで同じデータが見れるようにしつつ統計値のSSOT(Single Source Of Truth:信頼できる唯一の情報源)を実現しています。
顧客管理基盤
ROXXでは、求人企業様・人材紹介企業様・求職者様、の大きな3つの顧客ドメインがあります。
これらのドメイン間で相互に統合できるように注意しながらコンテキスト境界に沿ってシステムを分離し、既存のCRM(Customer Relationship Management:顧客関係管理)で事足りる部分はそちらを使ってもらいつつ、統合のためのデータスキームの設計やAPIサーバーの作成などを行っています。
それに付随して各種LP(Landing Page)の管理なども行っています。Miscチームの担当領域の中では最もフロントエンド側の開発が活発な領域です。
請求・契約管理基盤
今は各サービスごとに請求や契約が管理されてしまっており、実際の請求・契約業務にかなりの手作業が入ってしまっています。
既存のSaasで対応できる部分は対応してもらいつつ、各社内サービスとの統合のためのAPIや管理画面の提供などを行っていきます。
現時点ではまだZキャリア プラットフォーム上に載っているシステムをそのまま使って対応しており、今後適宜必要な機能を切り離していく予定です。
技術スタック
Miscチームではシステム間の疎結合性を重要視しています。イベントドリブンアーキテクチャを基本に据えるため、イベント駆動と親和性の高い技術スタックを採用しています。
CQRS+ES
CQRS(Command Query Responsibility Segregation)とは、コマンド クエリ責務分離のことで、read用DBとwrite用のDBを分離する手法のことです。
ES(Event Sourcing)とは、State Sourcingの対義語で、過去のイベントの積み上げが現在の状態を定義するという考え方です。私たちは、Event Sourcingをより厳密に適用するため、ドメインイベントに対するオブザーバーパターンによるイベントの永続化を採用しています。これには下記のような利点があります。
ビジネスドメインにおけるイベントへの関心と実装を同期させることができる。これによりアプリケーションによる手続き的な処理を減らして、イベントのpublishとsubscribeという形でドメイン内に責務を移すことができる。
現在の状態を復元できることがイベントの実装の最低要件として要求されるため、不適切なログ設計による過去の状態の喪失を避けることができる。
常に追記のみが行われて更新が行われないため、writerインスタンスのパフォーマンスを良好に保てる。
readモデルへの投影がコマンドから分離することで、readモデルの要求に特化したreadモデルを、readモデル側の責務で作成できる。
外部サービスへのイベントの送出をドメインモデルで表現することで、コンテキストマップに沿ったイベント設計を行うことができ、送出するべきイベントを正確に拾い上げることができる。
readモデルの同期が少し遅れるとか、結果整合性が必然的に求められるなど、すべての場面で必ずしも使えるわけではありませんが、MiscチームではまずCQRS+ESでシステムが構築できないか検討し、優先的に活用するようにしています。
GO言語とGCP
ROXXでは、長らくLaravelとAWSの組み合わせを採用してきましたが、MiscチームではGO言語とGCPを技術スタックの中心に置いています。
対象としている領域が既存のSaaSやBigQueryとの結合度が高いので、AWSに構築された既存サービスとのトラフィックがあまり気にならないというのもありますが、GCPの方がDXが高く、マイクロサービスを展開するには適切なプラットフォームであると感じています。
マイクロサービスではScalaなどのJVM言語が採用されることが多いですが、採用の市場感を考慮して見送りました。Go言語は言語仕様が簡素なため最低限読み書きできるようになるためのハードルが低い一方、機能面での取捨選択が適切に行われていると感じることが多く、基礎的なソフトウェア設計の知識さえあれば他言語の経験しかない人でもOJTを通じてキャッチアップしてもらえると考えています。
実装は原義的なCQRS+ESとオブザーバーパターンを採用しており、特定のフレームワークに対する知識などは必要ありません。
このような技術スタックを採用することで、フレームワークの使い方のようなことに学習コストを割かず、我々の目指すアーキテクチャ設計とビジネスドメインへの理解にキャッチアップのリソースを集中してもらえると考えています。
Zero trust architecture
Miscチームの扱う領域では従来の境界型防御を構築ができないシステムとの連携が求められます。そのため全体的なセキュリティ設計はZero trustの原則を指向しています。
可能な限り、サーバレスな構成を採用してCloud Platform側にセキュリティ責任を移譲し、我々はアクセスポリシーの制御に専念します。具体的な技術としてはWorkload IdentityやOpenID Connectなどを利用しています。殆どのアプリケーションはCloud Run / Cloud Functions + Firestore上に構築しています。
コンシューマ駆動契約とスキーマ駆動開発
コンシューマ駆動契約とは、マイクロサービスアーキテクチャにおける概念で、サービスを利用する側(コンシューマ)がサービス(プロバイダ)側に対して機能を要求し、それに対する契約としてプロバイダが機能を提供することを指します。Pactはこの契約が破壊されていないことをCI上で確認できるツールで、大規模な統合テストを行わず破壊的変更が起きていないことを検証できます。
スキーマ駆動設計は、まずサービス間のインターフェースをスキーマとして定義し、各々のサービスがそれを満たすように実装していく開発スキームです。スキーマ駆動設計の具体的な実装としてはOpenAPIがあり、スキーマ定義から各種言語用のクライアントを生成できます。
モノリスのシステムではサーバーサイドとフロントエンドの境界に採用されることが多いですが、マイクロサービスにおけるサービス間のインターフェースにも利用可能です。
Pactはインターフェースだけでなくデータの中身までテストとして要求できる、極めて安定性の高い仕組みですが、テストケースを追加する工数が比較的高いため、OpenAPIなどのスキーマを契約の中心に据え、スキーマだけでなく内容がクリティカルになる要件だけピンポイントでPactを利用することで開発工数と品質担保のトレードオフを調整することができます。
これ以外にも、様々な技術スタックを利用していますが、Miscチームとして特徴的な技術スタックはこの辺りになるかと思います。
最後まで読んでいただきありがとうございました!
Miscチームは技術採用の自由度も高く、色々なことに挑戦できる環境です。
今回ご紹介したチーム体制やアーキテクチャは、すべて現場から提案し、会社側との合意を得て進めている内容です。会社組織と開発現場との相互の信頼を維持できていることがROXXの強みだと思います。限定的な視野にとらわれず、組織レベルでの課題に対するソリューションを提案し、実行していくことも私たちのミッションです。
我々の将来の開発組織像へのビジョン・価値観を共有でき、そのうえで実践に至れる方、そしてこのnoteを読んでみて、ここに書かれているような新しい領域に挑戦してみたいと思っていただけましたら、気軽に下記よりご連絡ください。お待ちしています !
エンジニア向け採用ページもOPENしています。開発環境など含め、エンジニア向け情報をぎゅっとまとめていますので、ぜひご覧ください。
ROXXのプロダクト開発部門を中心に、Tech blogも更新中です。