🚪

実際の業務とDDD - スマートロック開発日誌 #2

2021/04/12に公開

この記事は、スマートロック開発日誌の第2回の記事です。

はじめに

ハコジムの業務で使用するシステムは、ドメイン駆動設計で開発しています。
今回はドメイン駆動設計の概要と、ハコジムのドメインについて紹介します。

ドメイン駆動設計とは?

ドメイン駆動設計とは、解決したいドメイン(システム化する業務の領域)の本質を明らかにし、ユーザと開発者の認識を一致させ、そこで作り上げたドメインモデルを元に実装することで、高品質なシステムを開発する手法のことです。ピンときた方もいると思いますが、ドメイン駆動設計はモデル駆動開発でもあります。

開発チームには開発者の他にドメインに詳しいドメインエキスパートが参加し、共通の言葉を使って議論します。議論する中でドメインモデルを作り上げ、言葉とモデルを洗練させることでチームの認識を合わせることができます。この共通の言葉をユビキタス言語と言います。これによって解決すべき問題とそれを解決するシステムの間に齟齬がなくなり、役に立つシステムを作ることができるわけです。もし解決すべき問題とシステムの間に齟齬があれば、役に立たないものが出来上がってしまいますよね。

また、ドメインモデルを洗練し本質に近づけることで、変更に強いシステムを作ることができます。なぜなら本質は変わらないものであり、ドメインモデルが変わるとしたら新たな概念の導入が主になるからです。つまり、システムに対する変更でなく追加が多くなることになります。

ユビキタス言語やドメインモデルは最初から完璧なわけではありません。継続的に洗練することで、より本質に近づけることが重要です。

あたりまえのことのように思えますが、意識してやらないとかなり難しいものです。そこでドメイン駆動設計の道具立てが役に立ってきます。それぞれの道具については適宜解説します。

ドメイン


まず、ハコジムのビジネスモデルからドメインについて考えてみます。
ハコジムが個室ジムを運営するためには、トレーナーと物件(店舗)、そして会員が必要になります。
このことから、最適な物件を探して出店する出店ドメイン、多くのトレーナーを採用するトレーナー採用ドメイン、多くの人に知ってもらうための会員獲得ドメイン、そして個室ジムを運営する個室ジムドメインが必要なことがわかります。

ここでは個室ジムドメインについて見ていきます。

サブドメイン

ドメインは複数のサブドメインに分けることができます。個室ジムドメインになくてはならない予約ドメインは、コアドメインと言います。今回開発するスマートロックドメインは、コアドメインの運用に必要な支援サブドメインと言えます。その他にも認証ドメインや顧客管理ドメイン、支払いドメインがありますが、どのドメインにも見られるようなサブドメインなので、汎用サブドメインと言えるでしょう。汎用サブドメインは、外部のサービスで代替することができます。

コンテキスト

同じ言葉でも、コンテキスト(文脈)によってその概念は違ってきます。例として、ユーザという言葉をみてみましょう。
個室ジムを予約するというコンテキストでは、ユーザは会費を払っていてアクティブか、パーソナルトレーニングを受けられるチケットを何枚持っているかに関心があります。
一方でスマートロックのコンテキストでは、ユーザがどのキーを持っていて、どのドアにアクセスできるかに関心があります。
これらを一緒に扱うこともできますが、分けて扱うほうが筋が良さそうです。

それぞれ予約コンテキストとスマートロックコンテキストとします。
これを境界づけられたコンテキストと言います。

コンテキストマップ

多くの場合、ドメインの中には複数のコンテキストが存在します。個室ジムドメインを例に取ると、中心となる予約コンテキスト、顧客管理コンテキスト、認証コンテキスト、スマートロックコンテキスト、支払いを扱うクレジットカード支払いコンテキスト、銀行支払いコンテキストなどがあります。

これらのコンテキストは密接に関係しており、この関係を表したものをコンテキストマップと言います。図中のU/Dは上流/下流を表します。四角の中の略語は追って説明します。

これらのコンテキストは単独で存在するわけでなく、お互いにコミュニケーションしてはじめて業務が成立します。しかし、同じユーザという言葉をとってもそれぞれ概念は異なります。そこでコンテキスト間でコミュニケーションするための戦略が必要になってきます。

スマートロックコンテキストではWebAPIを公開し、予約コンテキストはそのAPIを使用してコミュニケーションします。このように外部に公開されたサービスを公開ホストサービス(Open Host Service / OHS)と言います。また、APIはスキーマなどの形でコンテキストの概念を公開します。これを公表された言語(Public Language / PL)と言います。

予約コンテキストは、スマートロックコンテキストのWebAPIを使用してコミュニケーションするわけですが、何も考えないで使用するとスマートロックコンテキストの概念に侵食され、いずれはコンテキストの境界も曖昧になりカオスの様相を呈することは想像に難くありません。
そこで概念の翻訳を行い、侵食を防ぐ層が必要になります。予約コンテキストでは同期タスクとして実装されており、そこで概念の翻訳と情報の同期を行い、それ以外の部分にスマートロックコンテキストの概念が侵食することを防いでいます。実装方法は様々でこの限りではありません。このように概念の翻訳を行い、侵食を防ぐ層のことを腐敗防止層(Anti-Corruption Layer / ACL)と言います。

サブドメインとコンテキストは概ね一対一で対応していますが、支払いドメインに2つのコンテキストが見えます。これは、銀行の支払いコンテキストとクレジットカードの支払いコンテキストで概念が異なる上に、使用するサービスも異なるためです。
銀行の支払いコンテキストでは、銀行の支店コードや口座番号について関心がありますが、クレジットカードの支払いコンテキストでは、クレジットカード番号や有効期限について関心があります。また、オーソリなどのクレジットカード固有の概念も登場します。

コンテキストの実装

上図のように、コンテキストは多くの場合サービスとして実装されます。認証ドメイン、顧客管理ドメイン、支払いドメインのような汎用サブドメインでは、外部のサービスを利用しています。

コンテキストをサービスとして実装すると、サービス同士の影響が最小限に抑えられ、高凝集で疎結合になります。この特徴から、コンテキストマッピングはマイクロサービスと相性がいい設計パターンと言えるでしょう。

サブドメインとコンテキスト

個室ジムドメインのコンテキストマップを見ると、サブドメインとコンテキストが綺麗に対応しています。しかし、既存サービスから徐々に移行するような場合は、同じサブドメインでも既存サービスと新規サービスで異なる概念、つまり異なるコンテキストが共存することがあります。また、複数のサブドメインを横断するモノリシックなサービスが存在する場合、サブドメインを横断するコンテキストとして考えられます。

今回紹介した公開ホストサービス、公表された言語、腐敗防止層の他にも、上記のような複雑なコンテキストの関係に対処するパターンがあるので、調べてみることをおすすめします。

おわりに

ドメイン駆動設計の戦略的な側面を見てきました。
記事を書く上で、曖昧なところを勉強し直し理解が深まった気がします!
よりよい記事にしていきたいので、もっと知りたいことや分かりにくいところなどあれば、気軽にコメントください。

次回は、ユビキタス言語とドメインモデルを紹介する予定です!

Discussion