見出し画像

「ドメイン駆動設計 モデリング/実装ガイド」を読んでDDDを学ぶ。

どうも、たかふみです。

開発に携わっているプロジェクトではドメイン駆動設計(Domain-Driven Design)が取り入れられています。

「基礎からきちんと学んでおきたい」
「だけど、難しい書籍で心折れたくない…」
ということで、本書「ドメイン駆動設計 モデリング/実装ガイド」を読み始めました。
本記事には読んでいて重要だと感じたところ、覚えておきたいところをメモとして残しておきたいと想います。

第1章 DDD概要

■キーワード
DDD:開発手法の一つ
ドメイン:ソフトウェア、システム、プロダクト、サービスで課題解決する対象の領域
ドメインモデル(モデル):現実のモノを抽象化したもの

ドメインモデル

Q.良いモデルとは?

A.ドメインの課題を解決できるモデル
 
→そのためには何が必要?

1.ドメインエキスパート(ドメインに詳しい人)と一緒に作る。

→ユビキタス言語を作る
ドメインエキスパート、開発者問わない共通言語。
ドキュメント、会話、プログラムで使うことで認識を合わせる。

(メモ)
・他職種のメンバーとのコミュニケーションでズレを無くす
・スプレッドシートで管理するのが良いか…?
・作成に時間は要するが、新しく入ったメンバーの辞書としても活用できる

2.運用の中で改善していく

初めから完璧なものは作れない。運用の中で作り上げていく。
改善によって他の箇所にも変更が入るため、変更しやすい設計を行う。

(メモ)
・作って終わり、ではない。運用コストも考慮する必要がある。

DDD向きなのは「ドメインが複雑なもの」

逆に「シンプル」だったり、技術寄り(パフォーマンス重視)のものには向かない。

(メモ)
・DDDによる恩恵が導入コストより大きいかどうかの判断が必要。

第1章はDDDに関する基本的な内容でした。「実際に運用に導入するにはどうすれば良いの?」「実際の運用と本の内容と差異は無いか?」など気にしながら読み進めたいと思います。

第2章 モデリング〜実装

モデリングとは?

本書では「ユースケース図」「ドメインモデル図」を作る方法を指す。

1. ユースケース図を作成
"ユーザーがシステムで何ができるか"を可視化した図。
ドメインモデル図作成のスコープを考える。具体化することで、解決する課題が見えるので良いモデルを作ることに繋がる。

2. ドメインモデル図を作成
簡易なクラス図。システムの構成要素の関係性を可視化した図。
▼内容
・属性(プロパティ)
・ルール/制約(ドメイン知識)
・オブジェクト同士の関係
・集約の範囲

3.アーキテクチャを決める
各レイヤーに実装する方針を決める
▼ドメイン層オブジェクトの基本方針
・ドメイン知識(ドメインルール)はドメイン層に書く
・常に正しいインスタンスのみ存在させる
 1. コンストラクタでのバリデーション
 2. 適切なアクセス設計(public,private)

ユースケース図
ドメインモデル図

開発対象の整理を行う、というイメージで読みました。ユースケースの列挙はオフラインならホワイトボードで、オンラインならMiroのようなツールでメンバーと一緒に作成していくのが良いと思います。

第3章 DDD固有のモデリング手法 集約/境界づけられたコンテキスト

集約

強い整合性を持つオブジェクトのまとまり

・部員数が5人以上で部として承認できる
→部の承認状態と部員数は強く結びついているため1つの集約になる

・部、部員オブジェクトは部集約に、生徒は生徒集約に属する
→全オブジェクトがどこかの集約に属する

・部集約を操作する際は部オブジェクトから操作する
→集約を扱う際の親オブジェクトを「集約ルート」として扱う

・トランザクションを一つにする
部員オブジェクトを操作するときは部集約で取得して操作する。単体のオブジェクトの直接操作はしない。

メモ
適切なドメインを設計するには、上記のようなルールを把握しておく必要がある。

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

左:境界を引く前 右:境界を引いた後

モデルが適用される範囲を定義して、それぞれの範囲(=境界で分けられた領域)で言語の統一を目指す。境界を引かないと言語を統一させることが大変になるため。

本章の内容はDDD固有ということで、あまり馴染みのない考え方でした。それぞれ理解して使っていきたいと思います。

第5章 アーキテクチャ

どのアーキテクチャを使うか

■3層アーキテクチャ
プレゼンテーション、ビジネスロジック、データアクセス
✖️ビジネスロジック層が責務過剰になる
✖️ドメインルールがモデルとデータアクセスに分散する

■レイヤードアーキテクチャ
プレゼンテーション、アプリケーション、ドメイン、インフラ
○アプリケーション層に「ユースケース」、
ドメイン層に「ドメインルール」を実装できる
✖️ドメイン層がインフラ層に依存してしまう
 ドメイン層にリポジトリを置くと、リポジトリがDB,ORMに依存する

■オニオンアーキテクチャ
・依存は外から内側
・ユースケースとはアダプター(コントローラー)を通してやり取り
・ヘキサゴナルやクリーンアーキテクチャも思想は同じ。言葉の定義や層の境界が違うだけ
→DDDに向いている

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

■1コンテキスト = 1アプリケーションとして開発する方法

ECサイトの開発
「販売」「配送」「仕入れ」を別のアプリとして作る。

各コンテキスト同士の通信は同期(API)or非同期(キュー)で行う。
→リクエストを同期にする必要があるか、サービスダウンに備えるかのどちらかによって選択。

■パッケージで分ける方法
ディレクトリごとに分ける

アーキテクチャについての内容でした。以前、クリーンアーキテクチャについての書籍を読んだことがあったので、レイヤーの分け方や役割については理解しながら読むことができました。アーキテクチャは特にチーム内で共通認識を合わせて開発する必要がある部分だと思うのでしっかり把握した上で進めていきたい部分です。

▼参考になる記事

第6章 ドメイン層

■ドメイン層とは
ドメインモデルを「表現」「使用」するものを実装する層
※あくまでベストプラクティス

表現:エンティティと値オブジェクト

エンティティ→識別子で判定。可変。
値オブジェクト→で判定。不変。

エンティティ
名前や年齢は変わる(可変)
値オブジェクト
10円という価値は変わらない(不変)

使用:ドメインサービスとリポジトリ

ドメインサービス
→モデルをオブジェクトとして扱えない場合に使う

リポジトリ
・「集約ルート」に対して一つ。
・インターフェイス(実装はインフラ層)
・Listのように扱う
 ✖️ユーザー登録
 ○ユーザーを追加
・ファクトリ

▼参考になる記事

開発をしていてドメイン層って何を実装するレイヤーなんだっけ…となることがあるので、この部分はしっかり理解しておきたい部分です。著者のブログ記事↑も合わせて読むと良いと思います。

第7章 ユースケース層

■ユースケース層とは
ドメイン層のメソッドを組み合わせてユースケースを実現する層。
ドメインオブジェクトの生成、状態の変更、永続化

実装例

「タスクの期限日を延期する」ユースケースの場合。
what(何を)が実装されており、how(どうやって)は分からない状態

public class TaskPostPoneUseCase {
  public void タスク延期(タスクID) {
    Task タスク = タスクリポジトリ.取得メ(タスクID);
    タスク.タスク延期メソッド();
    タスクリポジトリ.保存(タスク)
  }
}

戻り値

専用の戻り値クラスを返す。(xxxDto)
ドメインオブジェクトを返す、という方法もあるが、表示に関する関数の実装が必要になる可能性がある。

分割の粒度

1クラス1パブリックメソッド
命名
・メソッド名+UseCase(CreateTaskUseCase
・クラス名+UseCase(TaskUseCase

第8章 CQRS:コマンドクエリ責任分離

DDDにおける参照系の問題と解決策

▼問題
・画面に表示しない値も取得することによるパフォーマンス悪化
・「複数の集約から値を取得&戻り値の型に詰める」実装が必要

▼解決策
更新系と参照系でクラスを分離する。
特定のユースケースに特化した値の型、Dtoクラスを作成する。

▼補足
・全参照系に使う必要は無い
ドメインオブジェクトの使用箇所が増えてしまうため必要に応じて。
・参照用モデルクラスはユースケース層に実装
特定のユースケースに特化したクラスのため。

第9章 プレゼンテーション層

■プレゼンテーション層とは
クライアントとアプリケーションの入出力を行う。
コントローラー、HTML、ルーティング。

・多くの場合、フレームワークに依存する層
・画面に表示する形式(日付表示、カンマ区切り…)はこの層に実装

DDDへの入門ということで本書を読みました。
どんなものなのかという概要は掴めたと思うので、見返しながら実際に実装していきたいと思います。

それでは!

読んでくださりありがとうございます。 これからもnoteで発信していくのでよろしくお願いします!