hosochinの技術ブログ

『ドメイン駆動設計入門』を読んで

はじめに

お世話になります、hosochinです。

今回は、『ドメイン駆動設計入門』を読みました。

📚 書籍情報:

私の現場ではいわゆる軽量DDD(ドメインエキスパートとの協働を省略し、技術的パターンだけを採用)が用いられています。

割とアンチパターンとして語られることが多いようで、本書でも「軽量DDDに陥らないために」という章があったりします。

ということで、なんとなくでしかDDDを知らない私が本書を読み、学んだことを書いていきます。

目次

  1. DDDの基本概念
  2. 値オブジェクトにする基準
  3. 可能な限りドメインサービスを避ける
  4. ドメインサービスの基準
  5. ドメインオブジェクトを定義するメリット
  6. 「仕様」による解決:趣旨が見えづらいオブジェクト
  7. 深い洞察を得るために
  8. まとめ

DDDの基本概念

本書で解説されているDDDの主要な概念は以下です。

【知識を表現するパターン】

  • 値オブジェクト
  • エンティティ
  • ドメインサービス

【アプリケーションを実現するためのパターン】

  • リポジトリ
  • アプリケーションサービス
  • ファクトリ

【知識を表現する、より発展的なパターン】

  • 集約
  • 仕様

まあ、大体なんとなくは知っていたので、それぞれの概念の説明は割愛します。 コラムとか筆者の考えが伝わる部分について、個人的なポイントをまとめます。

値オブジェクトにする基準

たとえば、以下のような可能な限り値オブジェクトを適用した FullName クラス

class FullName {
  private FirstName firstName;
  private LastName lastName;

  ...省略
}

// FirstName はこんな感じ
// LastNameも同じ感じ
class FirstName {
  private String value;

  ...コンストラクタ省略
}

firstNameとlastNameはStringでもいいのでは?と思ってしまう私はこれはやりすぎと思ってしまいますが、正しいと評する人もいるということです。 筆者はどちらも正しいと言い切れないとしながらも、1つの判断基準を示してくれています。

ドメインモデルとして挙げられていなかった概念を値オブジェクトにすべきかどうかの判断基準として、筆者は「そこにルールが存在しているか」という点と「それ単体で取り扱いたいか」という点を重要視しています。

FullName には「姓と名で構成される」というルールがあるため、筆者の判断基準に照らし合わせると値オブジェクトとして定義されます。

対して、FirstNameLastName については、今のところシステム上の制限もなく、それ単体を取り扱うシーンもないため、まだ値オブジェクトにしないということです。

まだ」というのがミソで、開発を進めていく中で、値オブジェクトとして定義する価値がある概念だと実装中に発見した場合は、ドメインモデルとしてフィードバックすべきとあります。

ドメイン駆動設計が目的とするイテレーティブ(反復的)な開発はこういった実装時の気づきによって支えられます。

可能な限りドメインサービスを避ける

無思慮にドメインサービスへふるまいを移設することは、ドメインオブジェクトをただデータを保持するだけの無口なオブジェクトに変容させる結果を招きます。

やろうと思えばいくらでもドメインサービスにドメインロジックを実装できますもんね。

ふるまいを値オブジェクトやエンティティに定義すべきか、それともドメインサービスに定義すべきかを迷ったら、まずは値オブジェクトやエンティティに実装してみましょう。その結果、不自然な実装になった場合にドメインサービスを検討するのが良さそうです。

ドメインサービスの基準

一般的に、ドメインサービスにはデータストアへのアクセスなど、入出力を伴う処理を持ち込むのは好ましくないと考えられています。

ただし、筆者は必ずしもそうではないと述べています。

筆者が重要視しているのは、その処理がドメインに基づくものかそうでないか、という点です。

可能な限り入出力はドメインサービスで取り扱わないようにするという方針には賛成です。それを考慮した上で、必要とあらば入出力の伴う操作をドメインサービスとすることも厭いません。

ドメインオブジェクトを定義するメリット

  • コードのドキュメント性が高まる
  • ドメインにおける変更をコードに伝えやすくなる

ドメインの表現が豊かであれば、後続の開発者にとってドメイン知識を理解するのに有効な手がかりとなります。

ソフトウェアが健全に成長していく未来を守るため、コードを饒舌にする努力は常に念頭に置くべき事項でしょう。

「仕様」による解決:趣旨が見えづらいオブジェクト

オブジェクトの評価処理を安直にオブジェクト自身に実装すると、オブジェクトの趣旨はぼやけます。

isXXX() が大量にできるパターンですね。分かります。

そうした評価の処理を放置しておくと、オブジェクトに対する依存度が増し、変更に弱くなります。そういう場合は 「仕様」として外部のオブジェクトに切り出す ことで扱いやすくなることがある、ということを知っておこうとありました。

深い洞察を得るために

開発者ドメインエキスパートの会話にはユビキタス言語を用いよう。

ユビキタス言語を使い会話をしていくと、ドメインの概念を伝える際に扱いにくい用語や曖昧な言葉に気づくことがあります。これこそが深い洞察のきっかけです。

どうして扱いにくいのか、開発者とドメインエキスパートで考え話し合っていくことで、よりモデルは洗練されます。

まとめ

『ドメイン駆動設計入門』を読んで、DDDは単に技術的なパターンを適用するだけではなく、ドメインの知識をコードに表現し、それを洗練させていく反復的なプロセスだということを理解できました。