KAKEHASHI Tech Blog

カケハシのEngineer Teamによるブログです。

「価値」から小さく始めるドメイン駆動設計

こちらの記事は カケハシ Advent Calendar 2023 の 16日目の記事になります。

概要

こんにちは。AI在庫管理の開発チームでSWEをしている小室です。

私は普段ドメイン駆動設計(以下、DDD)を意識しながら開発することが多く、実践を重ねるほどDDDの素晴らしさを実感しております。 最近異動してきたAI在庫管理の開発チームでは、現状はあまりDDDを意識して開発を進めていないのですが、プロダクトが対象としている世界が非常に複雑であることと、今まさに多くの法人様に利用していただけるようになったうれしい悲鳴として成長痛を感じ始めており、ドメイン駆動設計を何かのヒントとしてプロダクトによる価値提供速度を加速できればと考えています。

しかしながら、ドメイン駆動設計は独自の価値観や学習コストの高さから、まだ取り組んだことのないメンバーとしては大きな不安を感じる部分があると思います。

たしかにDDDの価値観や知識の範囲は広範かつ曖昧さを含んでいますが、その分懐の広さがあり、各人やチーム状況によって濃淡をつけながら取り組んでいくこともできると考えております。

本記事では、DDDの初学者を念頭に、筆者がドメイン駆動設計を実践する中で感じた価値を整理することで、考え方の部分からDDDを小さく始められるようにまとめていければと思っています。

DDDは未完成だ!

これから学習する方にとって、DDDというと構えてしまうところがあると思うのですが、 まずはDDDに明確な定義はないことを認識して、気楽に構えてみてはいかがでしょうか?

Evans氏は「DDDは未完成だ」と述べた。 (中略) ... 氏はDDDにとってのスイートスポットがあると考えている。ガイダンスが非常に厳格であると、ほんの些細な変化ですら「あなたはDDDをやっていない」と言われてしまう。 https://www.infoq.com/jp/news/2018/10/ddd-not-done/

プロダクトやチームの状況によって実践のスイートスポットは異なるはずなので、必要な部分をアレンジしながら取り入れていくのが大切だと思っています。 逆にDDDは掴みどころがないという様なネガティブなイメージを持たれることもありますが、アジャイルやスクラムのように原理主義になるより、必要なことを考えながら実践していくのが重要だと考えています。

ドメインを中心に考える

多くのエンジニアにとって、プロダクトを開発する意義は「顧客のなんらかの課題を解決すること」です。では、どの様にしたら日々の開発業務が顧客価値を中心にした作業とすることができるでしょうか?というと実際イメージが湧きにくいものではないでしょうか?

自省もこめて、エンジニアは往々にして技術的な詳細から考えてしまうことがあります。例えば、DBのテーブル構成やUIの組み方などの技術的な詳細から想像し、その実現性がイメージできないと不安を感じてしまいます。

しかし当然のことですが、顧客にとってDBに何を選定しているか?どんなテーブル構成か?UIライブラリがReactか?Svelteか?には全く関心がなく、どの様な価値が提供されるか?がより重要な関心事になります。

ドメイン駆動設計は、まさにこの考えの転換を促していると感じます。即ち、技術的な詳細よりもドメインにフォーカスしよう!ということです。

では、ドメインとはなんでしょうか? 個人的にはドメインという言葉は初学者にとって威圧的に響くポイントだと感じていますが、決して難しい概念ではないと思っています。ドメインとは単にプロダクトの扱う対象の世界のことです。つまり、どの様なユーザがいて、どの様な環境があって、どの様なことがしたいのか?がドメインに含まれます。 例えば、弊社の薬歴システムのドメインであれば、薬局・薬剤師・患者がいて、薬局には毎日処方箋を持った患者が来局し、薬局は処方箋を受け付けて薬剤師からお薬を処方したり服薬指導などを行って患者の健康をサポートしている、という世界が広がっており、この様な体系がドメインになります。 (ドメイン駆動設計ではドメインの境界や分離方法にも言及がありますが、その点は割愛します。)

ドメインを中心に考えるということは、システムの詳細ではなく、現実(ドメイン)の事情によりシステムを設計するということです。

抽象化を具体化することだと考える

抽象的という言葉を検索すると、2番目に「具体性を欠くさま。」という意味がでてきました。 一方で、抽象化という言葉をwikiで調べると以下の通りです。

抽象化とは、... 対象から注目すべき要素を重点的に抜き出して他は捨て去る方法である。

このように、抽象化することは、重要なものだけに絞るとことで、より具体的なイメージを切り出すことになります。

例えば一円玉が目の前にあることを想像し、それが何かを説明してみてください。 説明に当たって、表現可能な要素は無数に存在します。

色・形・大きさ・重さ・材質・年号・製造年月日・表面の模様・構成する原子数・etc...

しかし、通常私たちがこの状況を説明する場合は、たとえば「一円の価値を持った硬貨」と表現できます。この表現だと、製造年月日がわからないし、材質や重さや模様が思い出せないこともありますが、多くの人にとってそれは問題になりません。 これは日本で暮らしている私たちには自明のことですが、例えば宇宙の彼方から来た異星人は一円玉をどのように表現するでしょうか...

筆者はこの様に具体化する表現が抽象化だと考えています。抽象化は物事に視点を与え、より明確な理解を得ることです。

ドメイン駆動設計には、ドメインモデルという概念がありますが、これは前述のドメインを抽象化(モデル化)したものです。 ドメインは複雑なので、一円玉と同じように説明可能な要素が無数に存在しますが、顧客のペインを明確にし、解決するのに必要な要素に絞り込んでいく思考が重要になります。

ドメインモデルを描く

ドメインモデルを構築しよう!と思った時に、みなさんはどの様な成果物を思い浮かべますか? 例えば、UML図、ユースケース図、ディシジョンツリーなどを思い浮かべるかもしれません。 しかし、実はドメインモデルにも明確な定義がありません。ドメインを(前述の)抽象化したのがドメインモデルであり、ドメインの重要な要素が表現されていれば方法は自由だと考えています。

ただ、それだけだとドメインモデルをどのように構築していけば良いかイメージがつきません。 そこで、なぜドメインモデルを書く必要があるのかを考えてみます。 それは、ドメインに関する理解を集約して練り上げていくための場所にすることです。 ドメインモデルがないと知識が分散してしまいます。例えば、DBのテーブル設計や、ORMの操作、UIコンポーネントのインターフェイスや、ドメインエキスパートの頭の中や企画資料など、各所に知識が点在します。 しかし、システムを構築するということは非常に複雑な作業であり、分散した重要な概念の全てをほんの些細な間違えなく調和させる必要があります。さらに、現実のドメインは日々変化したり、よくよく考えるとドメインへの洞察(抽象化)が変化する可能性があるため、高い保守性を維持し常にupdateできる状態にしておく必要があります。 そのためには知識が集まる場所を作っておく必要があり、それがドメインモデルになります。

このように知識を一箇所に集積するメリットとしては、ドメインモデルが各メンバーの思考の橋渡しになることです。 例えば、ドメインエキスパートが顧客のことを一番よく知っており、またなんらかのイメージを持ってドメインを理解しているはずですが、そのイメージをエンジニアが直接見ることができませんし、そのままではシステムレベルでみた時に矛盾や飛躍が含まれていることが多くあります。 そのため、ドメインエキスパートの思考をドメインモデル上で整理することで、エンジニアに同じイメージが共有され、また、システムに落とす際の飛躍や矛盾を顕在化させて調整することができます。 また、エンジニア同士の溝を埋めるのにも有効です。例えば、バックエンドエンジニアがDBのテーブル構造を念頭に話し、フロントエンドエンジニアがUIコンポーネントの構成を念頭に話している状態だとうまく噛み合わないことがあります。ドメインを中心に会話することで概念が一つにまとまり、本当に大切なことを常に確認しながら作業を進めることができます。

さらに、知識が一箇所に構造的に整理されるようになると、知識間の関係性がわかってきます。例えば少し抽象的な表現ですが、機能Aと機能Bがあって、それを構造的に整理した結果、実は根本的には同じ概念として整理できるため、実装を共通化できることに気が付くことがあります。 逆もしかりで、ある機能Cが本来別の機能D, Eに分解されるべきであったことに気づくことができます。ドメイン駆動設計ではこれを知識の蒸留と呼んでいます。

モデルとは知識が蒸留されたものである。 (p.405)

システム思考という概念がある通り、確かに物事は単独で存在している訳ではなく、関係性として整理することで初めて理解できることがあります。知識間の整合性が取れていれば、より無駄なくスムーズに顧客へ価値提供ができるようになります。

ユビキタス言語を活用する

勘の良い方は↑で解説した部分からすでに気づいているかもしれませんが、ドメインモデルはチームメンバーの理解を集約する場所であり、そこには共通の語彙、即ちユビキタス言語が現れます。

ユビキタス言語はよく「ドメインの専門用語をまとめた辞書」と説明されることがありますが筆者は半分間違っていると考えています。 なぜなら、ユビキタス言語はドメインモデルを説明するのに使われる表現なので、単なる語彙集ではありません。 仮に辞書に起こしたとしても、正確に意味を伝えることや、メンテナンスが難しく、浸透もしないため形骸化することも多くあります。 言葉は、自然な文脈で使われることで初めて理解が進み、その用法やニュアンスを調整していくことができます。

また、筆者が特に重要と感じているのは日本語を利用することです。 原典引用すると、ドメインモデルの有用性の一つとして

生まれながらの言語能力を使ってモデルを改良できる

というものがあります。日本語のネイティブにとって細かな言い回しや表現は多くの情報を含んでいます。また、弊社のように国内向けのプロダクトを開発するチームにとっては、そもそもドメインそのものが日本語の空間であり、日本語により最も正確に抽象化することができます。 また、ドメインエキスパートの思考がそのままシステムの改良につながるように、ドメインモデルはそのまま実装に落とすことが推奨されています。そのため、コーディング時もドメインに関係する用語は基本的に日本語でコーディングすることを推奨したいと考えています。 (この点は以前、Qiitaに考えをまとめてみました。)

Qiita: Webエンジニアはそろそろ日本語変数名の利用を検討してもいいのでは?

原典の序章、第1章を読む

ここまで、記事を読んでみて多少なりともDDDに興味を持った方は、ぜひ原典の 序章、第1章 を読んでみてください。 DDDの原典であり、難読書として知られているエリック・エヴァンスのドメイン駆動設計ですが、序章と第1章は比較的読みやすく、DDDの価値観を理解する上で重要な部分が詰め込まれています。

DDDを学ぶ意義をより明確にすることで、学習がスムーズになると思います。

軽量DDD

DDDの世界を二分する概念として、戦略面戦術面という二つの側面があります。 戦術面は技術的な部分の設計手法です。戦略面はドメインエキスパートとの協業をスムーズにしたり、システム全体の構成を考えたりする時に使える概念が整理されている部分ですが、一方で抽象的な説明が多く、多くの初学者が挫折しやすい部分となっています。 また、DDDを始めるにあたって、「ドメインエキスパートの時間が確保できない」、というのが大きなハードルになることがあります。

そんな時は、まずはエンジニアだけで最初の一歩を踏み出すことにも価値があると考えています。 筆者がそう考える理由として、ドメイン駆動設計はエンジニアとドメインエキスパートが一緒になってドメインモデルを改良し続けますが、基本的にモデリングの作業自体はエンジニアがファシリテートしていくため、事前にエンジニアがモデリングに慣れておくと共同作業がスムーズに進みます。また、ドメイン駆動設計は、ドメインモデルをそのままシステムに落とすための手法が整理されているため、技術領域を理解しておくことで、ドメインモデルの価値に対する理解も深まります。

戦術面(技術面)だけを取り入れたDDDを揶揄する言葉として軽量DDDがありますが、最初から全てを完璧にこなすことはできないので、恐れずまずは軽量DDDから取り組んでみてはいかがでしょうか?

まとめ

ドメイン駆動設計の価値観や考え方を筆者の経験を元にまとめさせていただきました。 DDDは確かに抽象的で学習コストの高いものですが、その分、枠組みの中に広がりがあり状況に応じてスイートスポットを選択していくことができるものだと考えています。 DDDの価値観に共感することが実践の第一歩なので、ご自身が共感できるものから無理なく進めてみてください!