Azit Inc.

to Developer

複雑な事業ドメインをプロダクトで扱うためのチームでの取り組み

  • #プロダクト
  • #配送
  • #ドメイン駆動設計

2022.06.16

Sogame Masato

株式会社 Azit CTOの @Pocket7878 です.
今回は、CREW Expressのプロダクト開発チームで複雑な事業ドメインをあつかうプロダクトの開発をするためにチームで実施している取り組みを紹介いたします。

プロダクトの事業ドメイン

CREW Expressは、荷物の配送を実施してくださる配達パートナーと、配送の依頼をしてくださるクライアントという2つの種類のユーザーを扱うサービスです。
そして、配達パートナーさんは:

  • ギグワーカーとして単発の案件を実施してくださる方々
  • 私たちと連携してクライアントさん専属のシフトに入ってくださる方々
  • クライアントさんが直接管理しておられ我々のシステムを通して稼動している方々

と、主に3種類のグループに大別されます。
また、クライアントさんも:

  • 個人として利用される方
  • 企業アカウントと読んでいる企業単位のグループに所属し権限管理等をしながら利用される方

と、2種類のクライアントの方々がいらっしゃいます。
また、配送については:

  • クライアントさんが自社で管理されている方々と弊社からの専属の方々両方に送りたいといった場合や、逆に自社で管理されておられる方のみに送りたいといった、「誰に送りたいか」といったグループでのフィルタリング
  • 「冷蔵可能」のような特定のスキルを持った方にだけ送りたいといった配達パートナーの方のスキルでのフィルタリング

などの様々なフィルタリングであったり、

グループに応じての優先度や最適なルートなど、どの配達パートナーの方にどの案件をやってもらうべきかのディスパッチの部分であったり

配送の業務は、1箇所で複数の荷物をまとめて集荷し複数箇所に届ける場合や、配達の時間帯をしていただいてその時間に間に合うように逆算してマッチングを開始するであったり、自社配達員の払底に応じて一時的にリクエストをバッファリングしたりといった、リクエストの発行タイミングであったり..etc
と、配送の業務をとりまく軸だけでも様々な範囲と種類の情報をプロダクトで扱います。
そして、まだまだ事業で価値を提供できる領域を広げていこうとしています。

プロダクトのドメイン領域をコンテキストマップで分析

CREW Express コンテキストマップ

上述のように、CREW Expressは非常に多岐にわたる領域をとりあつかっています。
そのため、プロダクトで取り扱う領域の全体がどのようになっているかを俯瞰で把握して意識しておく事は開発において重要です。
そのため、チームでプロダクトのドメインの領域をコンテキストマップをつくりながら分析を行いました。

プログラムにドメインの構造を反映するためにRails WayからDDDに段階的に移行

開発当初から意識していた事

スタートアップは常に速度との戦いです、そのためには日々素早く仮説検証を回す必要があります。特にサービス初期は事業の根幹の仮説を確かめるために慣れた技術で素早く開発をする必要があります。
そのため、弊社で事業開始時点で社内の技術スタックとして一番慣れていたRailsで開発を行ってきました。
一方で、当初から意識していたのはプロダクトの規模が広がるにつれて発生する課題を避けるために以下の2つは特に意識して開発をすすめていました

  • TDDを実践し、ユニットテストやリクエストテストのカバレッジを高く保つ
  • RailsのActiveRecordのみにロジックを書きすぎず、PORO (Plain Old Ruby Object)でビジネスのロジックやドメイン上のロジックを記載する

プロダクトの拡大に応じて、よりDDD的な構造に移行

モデルをコンテキストに分割整理する

そのように開発を進めていたプロダクトですが、徐々に対応領域を広げていくにともなってよりPOROにも構造が必要になってきました。そのため、上記のコンテキストマップで整理した構造にもとづいて、models以下に一律で格納されていたモデルを、○○_contextといったコンテキストマップに対応したネームスペースに整理をしはじめています。

UseCaseやQueryの層をつくり、ドメインモデルと分離する

さらに、コンテキストで分離するのみでなくPOROで書かれているモデルを、ドメインのユースケースの表現のためのUseCase、表示用のデータを取りだすためにドメインの集約とは異なる切り口でデータを取得するQueryと分類し、use_casesフォルダとqueriesフォルダをつくり対応する分類へと整理をはじめています。
上記のようにすることで、ドメインモデルをあらわす処理とその他のロジックの部分との整理がすすみ、機能開発の時の新規追加や変更の箇所見通しが良くなり、テスタビリティもさらに向上したように感じます。
最初からUseCaseやQueryの層を作っておく必要はないとおもいますが、プロダクトをつくっていく中で、どの部分は意図的にRails Wayを外れるかというのを日々チームでのふりかえり会などを通して議論をしながら今の形になっています。

プロダクトを上での共通の技術的な知識を持つために読書会を開催

上記のように開発をすすめているチームですが、今のメンバーの知見を揃えるためであったり、将来の新しいメンバーにより良く技術的なプラクティスや知見を伝えるために読書会も随時開催しています。
今のところ、参加メンバーが全員すでに読んだことがある本をおさらいで読みながらチームで議論しておきたい部分を持ち寄って議論をしています。上記のコンテキストマップもその中の取組みの一つとして実施したものになります。
今までに読んだ本、これから読む予定の本は以下のものになります
テスト駆動開発 実践ドメイン駆動設計
セキュア・バイ・デザイン: 安全なソフトウェア設計 モノリスからマイクロサービスへ ―モノリスを進化させる実践移行ガイド

sudoモデリングを活用しながら要求分析を実施

すでにある程度複雑なドメインに、さらに日々機能を追加していく時にきちんとドメインにたいする知識を育てていくためには、1つ1つの機能がドメインにたいしてどのような変化をもたらすのかを意識しながら積みあげていく必要があります。
そのために、弊社の要求分析ではDDDの第一人者である松岡さんが考案されていた分析手法であるsudoモデリング

https://www.youtube.com/watch?v=A2EU0paEVJ0&feature=emb_title

を元に、要件をつくにあたって

  • システム関連図 (s)
  • ユースケース図 (u)
  • ドメインモデル図 (d)
  • オブジェクト図 (o)

を、ステークホルダー (クライアントであったり、サクセスやBizDev,セールス等の他チームであったり)と対話をしながら分析し、要件の解像度を高めながら分析を実施しています。
以前から要求仕様書とという形での要求の分析はチームに導入していました:

が、さらにここにsudoモデリングも付与する事でよりドメインの目線での解像度が高まったように感じています。

よりドメインの知識を扱いやすくするため、Goへの移行を計画中

上記のように、ドメインの知識やDDDの知識を深めながら日々開発しているプロダクトですが、よりドメインの知識を安定して表現しやすく、かつ生産性高く開発をするためにRailsからGoに移行する事を現在計画しています。
Railsの枠組みでは表現しづらい部分を表現しやすく、また静的型付けでドメインの条件などをチェックしやすい技術に移行したいという事は事業当初から考えており、その中で

  • Rust
  • Kotlin
  • Go

の候補にしぼって、移行先を検討していました。
その中で実際にDDD的な書き方をそれぞれの言語で実践してみて、どのように書きやすいのかを実際にチームの皆で比較してみながら、今後の事業の計画や様々な市場環境などを含めて総合的に判断してGoを選定しました。
(Rustは最適化エンジンのあたりでつかっているので、そのあたりはまた紹介します)

まとめ

今回の記事では、CREW Expressのプロダクトをとりまく事業ドメインを紹介し、複雑な事業ドメインに対処するためにバックエンドの開発チームで実施してきた事と今後の展望にフォーカスして紹介いたしました。
このようにCREW ExpressのバックエンドチームはシンプルなCRUDに落しづらい複雑な事業ドメインと向きあうために日々プロダクトについて議論をしながら開発を進めています。

https://meety.net/articles/t2--w-k3nxle8r

この記事をシェアSHARE

この記事をシェアSHARE

MORE ARTICLES