shimapapa.io

.NET,VB,C#,AzureなどMS関連中心の技術ブログ

【読了】「ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本」

前置き

今回はこちらの書籍の読了記事です。

ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本

ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本

  • 作者:成瀬 允宣
  • 発売日: 2020/02/13
  • メディア: 単行本(ソフトカバー)

ドメイン駆動設計の実装に関するパターンがサンプルコードを多数用いて紹介されており、
タイトル通りにボトムアップドメイン駆動設計を学べる内容となっておりました。

読書メモ

第1章 ドメイン駆動設計とは

感想

ドメインモデルとドメインオブジェクトの違いが明確になった。
ASP.NET MVC等のフレームワークでは実質Modelの区分とするのはDTO=Data Transfer Objectだったりするので、
DTOなどのモデルとドメインモデルの区別も今後は明確に線引きすることが出来そう。

第2章 システム固有の値を表現する「値オブジェクト」& 第3章 ライフサイクルのあるオブジェクト「エンティティ」

エンティティは以下のような特徴を持つ。

  • 可変である
  • 同じ属性であっても区別される(例:UserオブジェクトならUserIdのような識別子で区別されるべき)
  • 同一性を持つ

感想

これらの章を読み、モデル、オブジェクト、エンティティの違いをきちんと理解できていなかったと感じた。
エンティティという概念も、O/Rマッパー上でのエンティティとドメインにおけるエンティティを区別しておく必要がありそう。

第4章 不自然さを解決する「ドメインサービス」 & 第6章 ユースケースを実現する「アプリケーションサービス」

例えば「ユーザー名の重複を許可しない」ドメインのルールを、Userオブジェクト自身に表現するのは不自然。
その不自然さを解決させるために「ドメインサービス」を使う。

「アプリケーションサービス」は、ユースケースを実現する「オブジェクト」。
(「サービス」も「オブジェクト」という捉え方、これまで出来ていなかった。)

アプリケーションサービスの処理結果を、ドメインオブジェクトをそのまま戻り値とするかは重要な分岐点。
ドメインオブジェクトを戻り値とした場合、アプリケーションサービスを利用する側 = クライアントがドメインオブジェクトを操作できてしまうことになる。

ドメインオブジェクトを外部に向けて公開する選択肢は処理自体を単純なものにしますが、その代償として多くの危険性を内包してします。

「6.2.3 ユーザー情報取得処理を作成する」

ドメインオブジェクトを直接公開しない方針がお勧め。
非公開とする場合はDTOにデータを移し替えて公開する。

更新処理においてある特定の項目だけ更新したいといったケースに対応する場合、引数にデータを渡すか渡さないかで挙動を制御できるようにする。
この戦略を取る場合、情報が追加されるたびにアプリケーションサービスのメソッドのシグネチャが変更されることになる。
それを避ける方法としてコマンドオブジェクトを用いる戦略がある。

感想

サービスというとこれまでアプリケーションサービスの方しか認識できていなかったので、
新たにドメインサービスという概念を得られたのは良かった。

また、クライアント側でもそのままドメインオブジェクト(値オブジェクトやエンティティ)のまま扱えたほうが良いと思いこんでいたので、そうではないという方針が存在する事も学べた。

第12章 ドメインのルールを守る「集約」

オブジェクトは複数のオブジェクトがまとめられ、一つの意味を持ったオブジェクトが構築される。 オブジェクトのグループには維持されるべき不変条件が存在する。

デメテルの法則」はオブジェクト同士のメソッド呼び出しに秩序をもたらすガイドライン
デメテルの法則」ではメソッドを呼び出すオブジェクトは次の4つに限定される。

集約の内部データを外部から隠蔽するためのアプローチとして「通知オブジェクト」を使う方法がある。

第13章 複雑な条件を表現する「仕様」

「仕様」はあるオブジェクトがある評価基準に達しているかを判定するオブジェクト。
(「仕様」を「オブジェクト」として捉える = 「コト」をオブジェクトとして捉えるのは、オブジェクト指向を理解する上でかなり重要なポイントと感じる)

仕様はれっきとしたドメインオブジェクトであり、その内部でリポジトリを使用することを避ける考えもある。
その場合は「ファーストクラスコレクション」を利用することが選択肢に挙げられる。

第14章 アーキテクチャ

ドメイン駆動設計と同時に語られることが多いアーキテクチャ

ヘキサゴナルアーキテクチャとクリーンアーキテクチャはコンセプトは同じ。
クリーンアーキテクチャはコンセプトを実現する実装方法が明示されている。

第15章 ドメイン駆動設計のとびらを開こう

開発者はドメインエキスパートと協力して、ドメインにおいて有益な概念を作り上げなくてはならない。
開発者にはドメインエキスパートとの対話を手引し、システムにって役立つ概念や知識を引き出す使命がある。

  • ユビキタス言語
    • プロジェクト内で認識の齟齬や翻訳にコストをかけないようにするための共通言語
    • ドメインエキスパートの言葉をそのまま扱うことではない
    • 開発者とドメインエキスパート間で双方向に改良し合うことで、開発者はドメインの理解を、ドメインエキスパートは開発者が欲する知識がどういったものかの感覚を養っていく
    • ユビキタス言語はコードの表現として使われる
  • 境界付けられたコンテキスト
    • ドメインの国境のようなもの
    • 変化に対する摩擦を防ぐためには、モデルに対する捉え方が異なる箇所でシステムを分割する
    • 例えば「ユーザー」というオブジェクトに、「ドメインにおけるユーザー」と認証等の機能に用いる「システムとしてのユーザー」が必要となるケース
    • 別のコンテキストに別のモデルとして定義すればよい
    • 出来上がったそれぞれの領域ごとに言語の統一を目指す → 領域を分けること = 境界を分ける
    • コンテキスト同士の関係を定義し、ドメイン全体を俯瞰できるようなものとしてコンテキストマップを作る必要がある

Appendix ソリューション構成

感想

レイヤードアーキテクチャの構成として、

  • プレゼンテーション
  • アプリケーション
  • ドメイン
  • インフラストラクチャ

といった形に構成するのは把握していて、ドメイン(Domain)の中は「Model」「Services」と区切っていくのはイメージしていたが、
そこから「Circles」「Users」といったよう意味の単位で分割し、その単位内にオブジェクトとリポジトリやファクトリを同居させるという方針は目から鱗だった。
常にそれが正しいとは限らないが、パッケージを分ける際はリポジトリやファクトリといった属性ではなく、意味的なまとまりを意識すると良い。 書籍の例ではアプリケーション、インフラストラクチャも意味の単位で分割している。