バイセル Tech Blog

バイセル Tech Blogは株式会社BuySell Technologiesのエンジニア達が知見・発見を共有する技術ブログです。

バイセル Tech Blog

事業への理解と将来を見据えたDDDとオニオンアーキテクチャの採用

こんにちは。テクノロジー戦略本部 開発三部の今井です。
私は現在、顧客対応・SFAシステム(以下、CRM)のバックエンド・インフラ領域の開発に携わっています。
本記事では、CRMのバックエンドアプリケーションにDDDやオニオンアーキテクチャを導入した経緯や設計などについて紹介します。

CRMの背景・目的

バイセルではDXの取り組みのひとつとして、さらに多様な買取・販売チャネルに対応し、買取から販売まで一気通貫してデータを管理・活用する「バイセルリユースプラットフォーム Cosmos」(以下、Cosmos)の開発を進めています。

2023年12月期 通期決算説明資料

その中で私が携わっているプロジェクトでは、インサイドセールス部門で使用するCRMを開発しています。
主力事業である出張訪問買取の最初の入口となり、将来的にはマーケティング部やセールスコンプライアンス部等顧客対応のハブとなるシステムを目指しています。

2023年12月期 通期決算説明資料

CRMプロジェクトは2023年1月にキックオフされ、2023年10月にリリースしました。

既存システムへのデータ連携が必要となるアーキテクチャ

バイセルでは既にお客様の情報を管理するシステムを運用しています。
既存システムはGoogle Cloudを採用しており、マイクロサービスアーキテクチャで構築されています。
お客様の情報は多岐にわたり、顧客情報だけでなく査定依頼があった商材の情報やアポイントの情報なども含まれます。
それらのドメインごとに複数のマイクロサービスが存在し、それぞれのDBで分散して管理しています。

こういった状況と1stリリース時のスケジュールやコストを考慮し、既存システムのDBからデータを移行し、CRMを独立したシステムとして運用することは難しいと判断しました。
そのためCRMのDBへは既存システムに依存しないデータを、お客様に関する情報等依存するデータは既存システムのDBに蓄積する方針で進めました。

添付している図は簡易的なものです

しかし、将来的にはCRMへリプレイスしていくことから、CRMへデータを移行し独立したシステムとして運用できる必要があります。

添付している図は簡易的なものです

CRMのバックエンド開発における課題

これまでのCRMのバックエンド開発では、処理を一つの層(Controller層)に集約させてしまっていたことで生じる、開発および運用コストの増大と処理の複雑化という大きな課題に直面していました。

背景としては、開発の初期段階でMVCなどのアーキテクチャの導入を検討していたことがあります。
しかし、チーム内での議論や設計が想定以上に長引き、検証作業に要する時間も踏まえると、プロジェクトのデリバリースケジュールを担保することが困難であるという結論に至りました。

結果として、アーキテクチャの導入を見送り、当面は処理をController層に集約させる方針を取りました。
これは将来的に適切なレイヤーへの分割を見込んでおり、仮に一つの機能であっても、同一ディレクトリ内でファイルを細かく分割するなどの対策を講じていましたが、このアプローチの限界を感じ始めていました。

そのため運用を開始して数ヶ月が経過し、日々の開発プロセスが安定してきた現在、アーキテクチャの検討および導入を再開しようと判断しました。

リプレイスを見据えてDDDとオニオンアーキテクチャを採用

既存システムからCRMへリプレイスすることを見据えて、ドメイン駆動設計(以下、DDD)とオニオンアーキテクチャを採用しました。

なぜDDDとオニオンアーキテクチャなのか

CRMでは、既存システムにはない新機能の開発にも取り組んでいますが、主要な開発は既存システムとのデータ連携に関わるものです。
これには既存システムのAPI呼び出しやレスポンスデータのマッピングなどが含まれます。
したがって、既存システムで扱われているビジネスロジックを直接実装することはありません。

この背景を踏まえると、当初チーム内では「DDDやクリーンアーキテクチャのような複雑なアーキテクチャを採用するメリットが少ないと感じる。比較的シンプルなMVCの方が適切ではないか」という意見がありました。
私自身も、現時点での運用を考慮すると、この意見に一定の賛同を示していました。

しかし、将来的に既存システムとの連携を終了し、そのビジネスロジックをCRMのバックエンドで実装する必要があるという観点から、MVCで耐えうるのか疑問に感じました。

MVCのシンプルさは魅力的ですが、適切に全ての責務を分割できない場合、一部のレイヤーが過剰な責務を担うことになります。
これによりレイヤー間の依存度が高まり、コードの複雑性が増大するリスクがあり、結果としてシステムの可読性やテストのしやすさ、将来的な変更への対応が困難になる可能性があると懸念しました。

これらの懸念を踏まえ、DDDとオニオンアーキテクチャを採用することで、将来的にはDomain層や他の特定の層のみを変更することで対応できると考えました。
このアプローチにより、システムの柔軟性と拡張性を高め、将来的なリプレイスや機能追加にも対応しやすくなると判断しました。

そもそもCRMの「ドメイン」とは何か

DDDとオニオンアーキテクチャを採用する方針を決めた後、CRMのドメインとは何かを定義する必要がありました。

CRMプロジェクトが立ち上がった当初、私たちは最初に業務の理解を深め、分析を行うことから始めました。
これにはドメインモデルの構築やユースケースの洗い出しも含まれていました。

その後のステップとして、既存システムのドメインおよびデータモデルについても調査を進めましたが、設計当時の意図や背景を把握できるドキュメントが不足していたことから、既存のデータモデルを基にして、どのようなドメイン構造が存在するのかを分析する必要がありました。

分析を進めた結果、我々が策定したドメインモデルやデータモデルは、既存システムのそれらとは複数の点で相違があることがわかりました。

例えば「顧客」ひとつとっても、どの時点で顧客になるかは業務でどう扱っているかによって変わりますし、各部署によっても定義が異なる可能性があります。
既存システムでは、アポイントメントが確定されるかどうかに関わらず、一度流入があった時点で「顧客」として扱っています(=新規顧客情報として登録される)
我々としては、それは顧客ではなく「見込み顧客」であって、「顧客」になるのはまた別の段階だと考えています。

当時分析していた既存システムのデータ構造やドメイン(一部抜粋)

このようにドメインの定義が異なると、データモデルの相違に直結します。
したがって将来予定されるデータの移行時には、我々が設計したドメインやデータモデルに合わせて情報を再構築する必要が生じると判断しました。

一方で新機能の開発に伴い、既存システムでは取り扱われていなかった新しいドメインの定義も行っています。
そういった新しいドメインを、既存のドメインと同様に扱うことは適切か(=Domain ServiceやDomain Modelのレイヤーで扱うことは適切か)疑問に感じました。

この点について、新しいドメインと既存のドメインを統合的に扱うかどうかの問題を考察した結果、次の二つの方針を取りました。

  • CRM固有のドメイン:
    • 既存システムのドメイン、例えば顧客情報やコミュニケーションなどを直接CRMに適用することは不適切であると判断。
    • そのため、CRM専用に設計された新しいドメインをDomain層に導入する。
  • 「技術的関心事への委譲プロセス」というドメイン:
    • 既存システムとの連携におけるリクエストとドメインオブジェクト間のマッピングは、ドメイン要件ともビジネス要件とも言えますが、これを前者のドメインとは別に扱うことを選択。

具体的なイメージとしては、Domain層のDomain ServiceではCRM固有のドメインに対するビジネスロジックを扱います。
またDomain層の中にDelegateProcess層を設けて、既存システムのAPI呼び出しやマッピングの処理などのビジネスロジックを扱います。

特にDelegateProcessのアプローチはチーム内での共感を得ており、リプレイスを見据えた設計としても良い選択であると考えています。

※調査と設計の過程でこちらの記事を参考にさせていただきました。

最後に

これまでの考えをもとに現在各APIに導入を進めています。
全てのAPIに導入が完了したうえで、どのようなメリット・デメリットがあったか等については、機会があればブログで書こうと思います。

また個人的には、こういったアーキテクチャの話は技術に焦点が当てられる印象です(具体的にどう実装するかやGoでいうとinterfaceをどう使うか等)
そのためどう実装するかより、事業やシステムの将来を見据えてどう考えるかにフォーカスして記事を書きました。

バイセルではエンジニアを随時募集しております。興味のある方はぜひ以下の採用サイトをご覧ください。

herp.careers