Help us understand the problem. What is going on with this article?

わかった気になるDDD入門記事まとめ

はじめに

こんにちは。はじめまして。tarokamikazeです。
これは、社内勉強会用に参考資料をまとめたものです。

この資料のゴール

  • DDD専門用語について、どんなワードでググったらいいかわかるようになる
  • DDDを知らない人が、戦術的DDD(軽量DDD)だけでもやってみようかなという気になる

前段; MVCの限界

あえて過激に言うと。
ある程度の複雑度を持ったアプリケーションにおいて、MVCであるというだけで、 Fat ModelFat Controller は避けられない。
モデルの中を整理できるような設計思想が必要なのだ!
というか、モデルっていうな!!

参考

DDD概観

DDDとは

Domain-driven design (ドメイン駆動設計)
顧客と開発者が業務を戦略的に理解し、共通の言葉を使いながらシステムを発展させる手法

ドメイン駆動設計のメリットと始め方 ~ 1章「DDDへの誘い」

ドメインの中にあるコアとなる複雑さ、クリティカルなパートにフォーカスする
ドメインとソフトウェアのエキスパートが協力しモデルを探索する
モデルをはっきりと表現するソフトウェアを書く
境界づけられたコンテキストの中でユビキタス言語を話す

ドメイン駆動設計の道標

いつ誰がいいだしたの?

Eric Evans というひとが2011年頃に書籍 「エリック・エヴァンスのドメイン駆動設計」を出版。これが原点とされる。
その後、2015年「実践ドメイン駆動設計(通称 実践本、iDDD本)」が出版。この記事はこちらに依拠してます。

ドメインってなによ?

知識、影響、または活動の領域
問題領域、業務領域とも訳されます。ソフトウェアが表現する対象。例えば、人事評価システムであれば、従業員や業績が知識であり、目標設定や評価が活動に当たります

ドメイン駆動設計の用語と解説(抜粋版)

ふわっとしすぎてよくわからんのですが

DDDの領域は大きく分けて3つに分けられます。

開発思想:
システムの複雑性に取り組むために、業務の専門家と技術の専門家で言語・モデルの認識を合わせ、継続的に進化させていこう、という考え方
戦略的設計:
ドメインモデリングの前提を揃えるための、モデリング対象を定義する原則と手法(コアドメイン/サブドメイン、境界付けられたコンテキスト、コンテキストマップ等)
戦術的設計
モデルを具体的に表現するためのパターン(エンティティ、レポジトリ、レイヤードアーキテクチャ等)

なぜDDD初心者はググり出してすぐに心がくじけてしまうのか

DDDやると、なにがうれしいの?

プロセスやツールよりも個人と対話を、
包括的なドキュメントよりも動くソフトウェアを、
契約交渉よりも顧客との協調を、
計画に従うことよりも変化への対応を、

アジャイルソフトウェア開発宣言

と言われても、どんなふうに対話するの? どんなふうに変化に対応するの? という疑問は浮かぶでしょう。
DDDはその道標になります。

もうすこし具体的に言うと。

  • MVCだとよくおこる「このロジックはどこに書けばいいんだっけ...」という迷いが出ないので、プログラム設計がサクサクできる
  • プログラムが高凝集・疎結合になるので、メンテナンスコストが下がるし、バグがおこりづらい。特に致命的なビジネスロジック周りのバグを防ぎやすい
  • ドメインエキスパート = 事業領域(ドメイン)に超詳しいひとと、開発者が話しながら実装を進められるので、上流工程がスムーズにいくし、認識齟齬がおきづらい(個人的には、アジャイル開発における上流工程のデファクトスタンダードだと思う)

戦術的DDD

プログラムレベルでは、こういうパターンで設計したらいいですよ、というベストプラクティス。
個人やプロダクト単位で「とりあえずDDDやってみるか!」となったら、戦術的DDDから導入するのが王道。
プログラマーにはとっつきやすい部分。しかし戦略までやらないと、開発の辛さは(減りはすれども)消えないのだ......

ちなみに、戦術的DDDだけを導入している状態/開発方針を「軽量DDD」と呼ぶ。基本的にはアンチパターンと言われているので、はやく戦略も手を出してみよう。

ようするにどういうことよ?

以下のベストプラクティス、デザインパターンの一種

  • オブジェクト指向、クラス設計
  • 単体アプリケーション設計、モジュールの依存関係

全部これで書き換えなきゃいけないの?

DDDは設計・実装コストが高いので、複雑でつらい更新系処理からやってみよう。以下のようなルールで柔軟に考えるべき。

  • 原則、更新系のみに適用すべき。参照系に全然適用しない方がいい。CQRS(コマンドクエリ責任分離).
  • 単純な更新系処理ならば、設計・実装コスパがあわないのでやらんでもいい。
  • ビジネス的にコアな機能や、複雑な処理から手をつけ始めよう。

MVCでそれできるの?

MVCの考え方から脱却したほうが、すんなり理解できる。
iDDD本ではヘキサゴナルアーキテクチャを推していたが、正直ふわっとしすぎてイメージできなかった。
個人的には DDD + クリーンアーキテクチャ が最強。

下図でいう、Entitiesの部分がまるごとDDDの担当領域。

DDD + クリーンアーキテクチャ

実装から学ぶクリーンアーキテクチャ

なおここ数年では、 Ruby On Rails でDDDを導入した例もちらほら。

代表的なパターン

以下は、名前だけでも覚えていってください!

  • 集約(Aggregate)
  • 値オブジェクト(Value Object)
  • エンティティ(Entity)
  • リポジトリ(Repository)
  • ドメインサービス(Domain Service)

集約 / 値オブジェクト / エンティティ

集約

実践DDD本 第10章「集約」~トランザクション整合性を保つ境界~

値オブジェクト: 開発言語依存のプリミティブな型(stringとか)をラップしたもの。値依存のビジネスロジックはここに書く。不変(イミュータブル)で、IDをもたない。密結合なら、値をいくつか持っていい。(価格オブジェクトなら、金額とか通貨単位など)
エンティティ: IDで判別される値のかたまり。ユーザーとか。不変ではない。
集約: エンティティや値オブジェクトをまとめた塊。トランザクション境界(たとえば、どれかのエンティティの更新がコケたら全部コケてほしい)の単位でセットにしていく。

リポジトリ

  • 定義としては、集約を取得したり保存したりする入り口。
  • 実装的には、DBとか外部APIを叩くやつ。
  • ドメイン層(domain package)にinterfaceとして定義し、他の層から利用する場合はこのinterfaceに依存させる。実装はインフラ層に書く。

ドメインサービス

  • 単一の集約 / 値オブジェクト / エンティティ に依存させられないビジネスロジックをここに書く。
  • 例) ユーザーIDはユニークじゃなきゃいけないよ、というロジック
  • これがいっぱいできるのは設計がイケてない証拠。苦肉の策として使おう。

エンティティやリポジトリって、ORMのあれ?

ORMの定義は忘れろ。あれはDDDの用語を借りたナニカだ。

特にエンティティは、DTO的オブジェクト<-->DDD的エンティティへの値の詰替が推奨される。
詰替はだるいが、それが戦術的DDDなのだ。がまんしよう。
この値詰め替え実装コストが、戦術的DDDの実装コストの代表例といってもいいくらい。

DDDの開発思想

ユビキタス言語

ユビキタス言語とは、開発者とドメインエキスパートなどシステムの開発に関わる人達全体のコミュニケーションを円滑に、曖昧さをなくすために厳格に定義された共有言語

ユビキタス言語の用語管理について調べた

ドメインエキスパート = 事業領域(ドメイン)に超詳しいひとと、開発者の用語と、クラス名やメソッド名をそろえよう。そうすれば上流工程もすんなりいくし、改修もかんたん。

ドメインエキスパートと開発者が言語 = 認識を合わせていけば、齟齬も生まれにくいものだ。
ドメインエキスパートが社内にいない? ならば君がドメインエキスパートになるしかないのだ!!
ユーザーインタビューに行きまくるしかない。

余談; UI/UXの世界でも

デザイナーの世界でも、概念モデルベースで設計しようぜ!的なことをが語られていますね。

OOUI

OOUI – オブジェクトベースのUIモデリング

戦略的DDD

戦術の失敗は戦略で補うことが可能だが、戦略の失敗は戦術で補うことはできない

軍事入門/戦略的な思考法

戦術的DDDに慣れてきたら、戦略的DDDにもトライしてみよう。
そもそものアプリの建付けからメスをいれるのだ!

ドメイン? コンテキスト???

境界づけられたコンテキスト

実践DDD本 第2章「ドメイン」「サブドメイン」「境界づけられたコンテキスト」を読み解く

境界づけられたコンテキスト = マイクロサービスの境界

システムが大規模になると、関係者すべてで統一したモデルを作ることは難しくなる
大きなシステムを「境界づけられたコンテキスト」に分割し、それぞれの中でモデル、言語の統一を目指す

コンテキストをわける

境界づけられたコンテキスト 概念編 - ドメイン駆動設計用語解説 [DDD]

マイクロサービスをやりたいんだったら、戦略的DDDもきちんとやりましょう。

どんな単位で切ればいいのさ?

エンジニアリング組織論への招待でも、two pizza rule で分けろと言われている。
いろいろ話をきいた結果、逆コンウェイの法則(組織にあわせてシステム設計する)のが正解っぽい。
つまり、1コンテキスト = 1マイクロサービス = 6~12名。

ユーザー部門で切ればいいの?

そういうわけではない。とにかくシステムが高凝縮になるように、いいかんじに切れればいい。
ECシステムだったら、以下みたいに切っている例もあるらしい。

  • カート
  • 決済
  • 商品(一覧とか更新とか)
  • 配送

まとめ

戦術的DDD(軽量DDD)から、雑にトライすればいいんじゃないかな。
勇気を持って学習棄却していこう。知的蛮勇を持っていこうぜ!!

tarokamikaze
PHPer -> Gopher だけどDDD信者。 上流/マネジメント/AWS/Heroku/Salesforce/GCP/スクラム なにおじさんかわからなくなってきた。
seeds_company
世の中をハッピーにし、ワクワクドキドキする世界を作りたい。テクノロジーの力で人材業界を変革し、企業の採用問題を解決すると同時に、はたらく個人個人が正当に評価される世界を目指していきたいと思っています。
https://www.wantedly.com/companies/seedscompany-persol
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away