Domain Driven Design
そもそもドメイン駆動設計(DDD)って何?
「 ソフトウェアで解決したいこと(=ドメイン)を中心に考えて設計するやり方 」。
普通の開発だと、データベースのテーブル構造とか、画面のデザインとか、技術的なことから考え始めちゃうことがあるんだよね。 「 そもそもこのシステムって、誰のどんな問題を解決するんだっけ?*」っていう、ビジネスのルールや課題そのものを一番大事にするんだ。
例え話で考えてみよう!
DDD を理解するために、「カフェの注文管理システム」を作るって想像してみて!
登場人物
- ドメイン(Domain): ソフトウェアで解決したい問題領域。今回の場合は「カフェの運営」
- ドメインエキスパート(Domain Expert): その道のプロ。つまり、カフェの店長さんやベテラン店員さんのこと。注文の受け方、割引のルール、在庫管理とか、ビジネスのことに一番詳しい人たち。
- 開発者: 私たちエンジニアのこと
DDD の重要な考え方
DDD にはいくつか大事な考え方があるんだけど、特にこの 2 つがキモなんだ!
1. ユビキタス言語 (Ubiquitous Language)
「みんなで使う共通言語」
開発者とドメインエキスパート(店長さん)が、会話で使う言葉とコードで使う言葉を完全に一致させるのが大事なの。
ダメな例
店長さん: 「お客さんが商品を注文したら、伝票をキッチンに回して…」
開発者: (ふむふむ、users テーブルのレコードが items を order したら、slips テーブルにデータ作る感じかな…?)
これだと、会話の言葉(商品、注文、伝票)とコードの言葉(user, item, order, slip)が微妙に違ってて、だんだん会話が噛み合わなくなっちゃうリスクがあるんだよね
良い例 👍
みんなで会議して、言葉を統一する。
「注文のことは、これからは必ず『オーダー』と呼びましょう」 「注文された個々の商品のことは『オーダー品目』にしましょう」 「お客さんのことは『顧客』と呼びましょう」
こうやって決めた「ユビキタス言語」を、会話でも、設計書でも、そしてソースコードのクラス名や変数名でも徹底して使うんだ。
ユビキタス言語の「オーダー」をそのままクラス名にする
class Order < ApplicationRecord
「顧客」がいて、「オーダー品目」がたくさんある、というビジネスルールをコードで表現
belongs_to :customer
has_many :order_items
こうすることで、エンジニアじゃない店長さんがコードを見ても、なんとなく何をしてるか想像しやすくなるし、認識のズレが劇的に減るんだよ
2. モデル (Model)
これは、ユビキタス言語を使って表現された「ビジネスルールの塊(かたまり)」のこと。
さっきのカフェの例で言うと、「オーダー」っていう概念には、色々なルールがくっついてくるよね。 合計金額は、オーダー品目の合計である。 テイクアウトの場合、消費税が 8% になる。 セット割引を適用できる。 こういう複雑なルールや知識を、データとロジック(処理)をセットにして表現したものが「モデル」なんだ。
Ruby on Rails と DDD の関係
「あれ?Rails の app/models もモデルって言うよね?」って思った? その通り!
Rails のアーキテクチャは、実は DDD の考え方にすごく影響を受けてるんだ。 でも、Rails のデフォルトのやり方だけだと、ちょっと困ったことが起きやすいの。
Rails でよくある悩み:「Fat Model」問題
Rails は Active Record っていうパターンを採用してるから、app/models にあるモデル(User とか Post とか)が、データベースとのやり取りも、ビジネスロジックも、バリデーションも…って、色々な仕事をやりがち。 アプリが小さいうちはいいんだけど、大きくなってくると、1 つのモデルファイルが数千行にもなって、何が何だか分からなくなる…
これが Fat Model(太ったモデル) 問題!
そこで DDD の出番!
DDD の「関心事の分離(役割ごとにファイルを分ける)」っていう考え方を使って、この Fat Model を解消するんだ! 例えば、app ディレクトリの下に、新しくディレクトリを作って役割を分担させる感じ。
-
app/services/
複数のモデルをまたぐような、複雑なビジネス処理を担当する専門家を置く場所。 例: UserRegistrationService(ユーザー登録に関わる色々な処理をまとめる)
-
app/forms/
ユーザーが入力したデータのバリデーションだけを担当する専門家を置く場所。 例: SignUpForm(サインアップ画面の入力チェックだけやる)
こんな風に、Order モデルが全部やるんじゃなくて、「オーダーを登録する専門家」「オーダーの金額を計算する専門家」みたいに、役割分担させてあげるんだ。 こうすることで、一つ一つのクラスはスリムで分かりやすくなるし、変更も楽になるんだよね!
まとめ
DDD は、ビジネスのルール(ドメイン)が主役の設計思想だよ! 「ユビキタス言語」っていう共通言語で、みんなの認識を合わせるのが超大事! Rails の Fat Model 問題を解決するのに、DDD の考え方がすごく役立つよ! DDD は結構奥が深くて難しいんだけど、「ビジネスの関心事をコードの中心に置く」「役割ごとにちゃんとファイルを分ける」っていう意識を持つだけでも、コードの綺麗さが全然違ってくると思う!