🍎

ドメイン駆動設計 完全に理解した(社内向け資料)

2024/03/14に公開

はじめに

これは「設計ってどこから始めていいか分からない」「そもそも設計する必要ってあるの?」「DDDってなに?」「デザインパターン聞いたことくらいは…」などの方を対象に、設計の価値を感じてもらう資料です。

設計の基本的な考え方から、ドメイン駆動設計を「完全に理解した」状態になるまでを目指します。

ちなみに、

完全に理解した曲線

引用: https://zenn.dev/activecore/articles/9862409de182c7

設計するのって何のため?

Q.ファイル分けずに1つのファイルに書いた方が楽じゃない?

メリット

  • 人間の思考の流れに近い(手続き型)

デメリット

  • 目的の処理を行っている箇所を見つけるのが大変
  • 1つのファイルが数百行、数千行に及ぶことになる

Q. コメント書いたりprivate関数に分ければ良くない?

メリット

  • 処理に説明や名前が付けられるので目的の処理を見つける手助けになる

デメリット

  • 1つのファイルが数百行、数千行に及ぶ状況は変わらない
  • 数百個のprivate関数が1ファイルに存在した処理を見つけづらい
  • 他のファイルに同じ処理が散在して修正時に修正漏れが起こりやすくなる
  • テストができない(やろうとすればできる)

Q.他のファイルでも使う処理は共通で切り出せばいいの?

メリット

  • 1つのファイルの行数が少なくできる
  • 処理の修正時に修正漏れが起こる可能性を低減できる
  • テストができる

デメリット

  • どの単位で処理を切り出せばいいか検討する必要がある
  • 切り出す単位によってはかえって読みづらくなる可能性がある

Q.じゃあエンジニアが各々の判断で切り出してOK?

メリット

  • チームで共通認識を取る必要がない

デメリット

  • 他のエンジニアが書いた箇所を理解するのに時間がかかる
  • 他のエンジニアが書いた箇所を利用したコードが書きづらい
  • レビュアーに1から説明する必要がある
  • 切り出す単位が適切ではない可能性がある

Q.じゃあどういう単位で切り出せばいいの?

  • MVCパターン
    • モデル、ビュー、コントローラー
  • デザインパターン
    • ファクトリ、リポジトリ、ファサード、etc...
  • ドメイン駆動設計
    • エンティティ、値オブジェクト、集約、リポジトリ、etc...
  • クリーンアーキテクチャ
    • ユースケース、プレゼンター、エンティティ、etc...
  • アトミックデザイン
    • Atoms, Molecules

設計パターンを学ぶのは何のため?

開発上の共通言語ができる

以下の会話で意思疎通ができる

  • この整形処理は複雑なのでコントローラーに書いてビューと分離しよう
  • 事業上重要な要素だからエンティティとして用意してそこに必要な処理を書こう
  • 一連の決まった複数の処理を行うことが分かっているのでファサードを作ろう

開発上の語彙が増えるのは大きな利点

例えば、ミーティングや朝会という語彙が無かった場合は、以下のように都度説明しなくてはならない。

  • 明日、先方を含めて会議室で話す朝のタイミングで要件の確認をさせてください。

ドメイン駆動設計って?

事業上重要な要素に焦点を当て、そこから設計しようとする手法。

詳細は以下のスライドでも紹介しています。

コード設計 - ドメイン駆動設計入門 | Canvaコード設計 - ドメイン駆動設計入門 | Canva

ユビキタス言語

システム開発において「開発者、クライアントなどプロジェクトに関わる人全体で作り上げ共有する言語」

引用: https://pivot.jp/column/system-2/#:~:text=ユビキタス言語とは?,開発が進められます。

ユビキタス言語を定義することは、プロダクト内でもコミュニケーションを円滑に行う際にはもちろん、クラスや関数を設計する際にも非常に役に立ちます。

クラスや関数の命名の際に意識すると良いことは以下のスライドにまとめてあります。

コード設計 - 名前設計 | Canvaコード設計 - 名前設計 | Canva

値オブジェクト

言語で用意されたプリミティブ型の変数や配列を用いる代わりに、専用のクラスを用意して扱うようにします。
クラスに値とセットで業務ロジックを盛り込み、必要であれば不正な値のチェックを行います。

値オブジェクトの性質

  • 不変である
  • 交換が可能である
  • 等価性によって比較される

メリット

  • ドメインをコード上で正確に表現できる
  • 同じ目的のロジックが色々場所に乱立することを防げる
  • 不正な状態の値が存在することを防げる
  • テストにより変更容易性を向上できる

デメリット

  • ファイルが爆発的に増える
  • 値オブジェクトを作るかどうかの基準が難しい

値オブジェクトの詳細は以下のスライドにまとめてあります。

コード設計 - 値オブジェクト | Canvaコード設計 - 値オブジェクト | Canva

クラスを分割する単位の参考になる情報は以下のスライドにまとめてあります。

コード設計 - DRY原則 | Canvaコード設計 - DRY原則 | Canva

エンティティ

言語で用意されたプリミティブ型の変数や配列を用いる代わりに、専用のクラスを用意して扱うようにします。

エンティティの性質

  • 可変である
  • 同じ属性であっても区別される
  • 同一性によって区別される

メリット

  • ドメインをコード上で正確に表現できる
  • コードのドキュメント性が高まる
  • ドメインの変更をコードに伝えやすくする

デメリット

  • 値オブジェクトなのかエンティティなのかの判断基準が難しい
  • 設計手法によってエンティティの解釈が異なる

リポジトリ

データにまつわる処理を分離し、永続化(保存)や再構築(復元)を担うクラス

メリット

  • データ取得の処理を他のレイヤーから隠蔽し抽象化することができる
  • データストアの差し替えを容易にする

デメリット

  • どの単位でリポジトリを作成するとよいかの判断が難しい(テーブルごと?エンティティごと?)

リポジトリやレイヤーの話はこちらのスライドにまとめてあります。

コード設計 - レイヤードアーキテクチャ | Canvaコード設計 - レイヤードアーキテクチャ | Canva

集約

データの変更をする単位として扱われるオブジェクトの集まり
ルートとなるオブジェクト(値オブジェクト、エンティティ)を用意し、すべての操作をそのルート越しに行います。
リポジトリは、集約の単位で作成するのが好ましいです。

参考文献

https://www.shoeisha.co.jp/book/detail/9784798121963
https://www.shoeisha.co.jp/book/detail/9784798131610
https://www.shoeisha.co.jp/book/detail/9784798150727
https://gihyo.jp/book/2022/978-4-297-12783-1

Discussion