エリックエバンスのドメイン駆動設計の「第9章 暗黙的な概念を明示的にする」まとめ

エリック・エヴァンスのドメイン駆動設計

エリック・エヴァンスのドメイン駆動設計

今回は、「第9章 暗黙的な概念を明示的にする」のまとめです。

概要

ユーザの活動や問題、その解決策に関する本質的な知識は、ドメインの中心となる概念によってシンプルに表現できます。

概念を明示的にするための最初のステップは、ドメインにおける本質的な概念をモデルで表現することです。

その後、ドメインモデルとコードが大きく変化するのは、ドメインエキスパートとのコミュニケーションであったり、設計の中に暗に存在する概念に開発者が気づき、モデルの中で明示的に表現したときです。

こうした変化によりブレイクスルーになることもあるが、まずは暗黙的な概念を荒削りであってもモデルで表現することが大事です。

概念を掘り出す

暗黙的な概念を掘り出す手段としては、コミュニケーションと設計の両方のぎこちなさがあります。

コミュニケーションきごちさな

コミュニケーションのぎこちなさとは、例えば以下のような点があります。

  • 開発者が特定のフレーズを使ったときに、ドメインエキスパートが困惑した状況になるか。

  • ドメインエキスパートの言葉の選び方に注目するして、開発者が新しい言葉を耳にするか。

  • ドキュメントに記述された言葉と話す言葉にズレがないか。

コミュニケーションのぎこちなさに敏感になることによって、モデルにとって有益になり得る概念を示す手がかりとなります。

また、ドメインエキスパートがドメインモデルにない語彙を使用したら警告サインで、さらに、ドメインエキスパートと開発者の両方ともドメインモデルにない語彙を使用したら2倍の警告サインとなります。このような状況を好機と捉えて、その語彙を取り込むことでモデルとコードを改善するよい機会となります。

設計のきごちなさ

設計のぎこちなさとは、例えば以下のような点があります。

  • 新しい要求が出てくるたびに複雑さが増しているようなところ

  • 説明しにくい複雑な処理をおこなっているところ

僕の経験からすると、複雑すぎて、本来の責務外の仕事もやっていても気づけないという状況がありました。本来の責務外の仕事をしているので、より複雑になってしまう。という負のスパイラルです。

複雑な処理をしているところは、処理に対するドメイン側の活動における目的や背景を理解するところからスタートすべきかと思います。

それほど明白ではない概念をモデル化する方法

明示的な制約

制約は、モデルの概念において、とりわけ重要なカテゴリなので、明示的に表現することによって、設計が大幅に向上します。

制約を独立したメソッド・クラスにすることによって、メソッド・クラスに意図の明白な名前をつけることができドメインモデル上でも制約を表現できます。

制約を独立したオブジェクトにしたほうがいいケースとしては以下のような点があります。

  • 制約を評価するために、本来であればオブジェクトの定義に合わないデータが必要。

  • 関連するルールが複数のオブジェクトに出てきて、コードを重複する必要があったり、本来であれば同じ系統でないオブジェクトを継承する必要がある。

  • 設計や要求に関する会話が制約をめぐって行われるが、実装では制約が手続き型のコードの中に隠されている。

独立したオブジェクトにする場合の置き場所は、ドメイン層になります。

ただ、僕は実プロジェクトで失敗したんですが、制約を何でもかんでも独立したオブジェクトにしてしまって、魂の抜けたエンティティや値オブジェクトが出来上がってしまいました。

なので、制約を使い始めの時は、独立したオブジェクトにするかどうかを慎重に議論したほうがよいと思います。

ドメインオブジェクトとしてのプロセス

ドメインオブジェクトとしてのプロセスは明示すべきプロセスであり、ドメインモデルに表現すべきです。

明示すべきプロセスと隠蔽すべきプロセスを区別する鍵は、ドメインエキスパートが話題に上げるか、コンピュータプログラムに置ける仕組みの一部にすぎないか。です。

仕様

概要

ビジネスルールは、エンティティや値オブジェクトの責務にどれも合致しないことがあったり、合致してもエンティティや値オブジェクトの基本的な意味を圧倒しかねないです。

このようなケースの対処として、特殊な目的を持った値オブジェクトを明示的に作成します。

この値オブジェクトのことを仕様と呼び、仕様とはあるオブジェクトが何らかの基準を満たしているかどうかを判定することです。

仕様の適用と実装

仕様の具体的な用途としては、以下3点あります。

①検証

オブジェクトを検証して、何らかの要求を満たしているか。を調べます。

例えば、有料会員サービスでの請求業務だと、過去に料金未回収になった会員(ブラックリスト会員)か?という検証があります。

この検証を独立したオブジェクトで表現するのか?会員の1メソッドで表現するのか?は、その時次第かと思います。

②選択

一覧から特定の条件を満たしたオブジェクトを選択します。

先ほどの有料会員サービスの続きの例で進めますが、全会員の中からブラックリストの会員一覧を取得する。という選択があります。

具体的な手段として、DDD本では

  1. SQLで対象者を選択するのか?

  2. SQLでは全会員を抜き出して、アプリケーションコードで選択するのか?(検証の例で書いたクラスかメソッドを利用)

がありました。

ただ、どちらの手段でも、抽出条件はドメイン層で定義しています。なので、「1」案だとSQLのWHERE句をドメイン層に記述する必要が出てきます。

性能として問題なければ、「2」案の手段のほうがドメイン層の責務がはっきりします。(さすがにSQLドメイン層に記述したくないので。。)

③要求

何かの仕様に適合する新しいオブジェクトの生成を定義します。

先ほどの有料会員サービスの続きの例で進めますが、ブラックリストの会員一覧が必要なときに、

  1. ブラックリスト会員一覧というオブジェクトを明示的に表現する。

  2. 会員一覧というオブジェクトで表現され、その一覧がブラックリスト会員になっている。ただし、会員一覧なので、使い方次第ではブラックリスト会員以外も入ってくる。

の表現方法があります。

「1」案だと、ブラックリスト会員という仕様に適合したブラックリスト会員一覧の新しいオブジェクトを生成するという責務があるので、今回の要求に該当します。

「2」案だと、会員一覧というオブジェクトが必ずしもブラックリスト会員のみという仕様を満たしていないので、今回の要求に該当しません。

まとめ

暗黙的な概念を明示する一番の効果的な手段は、ドメインエキスパートとのコミュニケーションで、特にコミュニケーションのズレ・ぎこちなさに敏感になれるかだと思います。

実際、ズレ・ぎこちなさに気づけても、それをドメインモデルまで(コードも)反映されることが大事になります。

なので、まずはドメインエキスパートとしっかりコミュニケーションできる環境が大事ですね。

以上が「第9章 暗黙的な概念を明示的にする」のまとめです。