それほど明白でない概念をモデル化する方法
よくあるオブジェクト指向の入門書では、「名詞(属性)・動詞(メソッド)」と説明されますが、名詞・動詞以外の概念をモデルで表現することができます。
書籍の中では、「制約」「プロセス」「仕様」について説明されていますので、読んでいきます。
制約
書籍ではバケツの例を上げています。
「バケツには、最大容量以上は追加できない」という制約ですね。
リファクタリング前では、「注ぐ(pourIn)」というメソッドのなかでif文制御していますが、制約を明示的に表現するために「最大容量以下に制限する(constrainedToCapacity)」というメソッドを追加しています。
このリファクタリングの効果は
- 制約に名前が付くので議論がしやすい
- 制約を変更しやすい
- 他の制約も追加しやすい
- 呼び出し側(バケツの例ではpureIn)がシンプルになる
といったいい効果があるので今すぐ実践したいところですね。
複数のオブジェクト間で成り立つ制約
上記の例は1つのオブジェクトに制約を表現したメソッドを追加しましたが、中には、複数のオブジェクトにまたがる制約もあるかと思います。
そんなときは、制約を取り出してオブジェクトにすると表現がしやすくなります。
書籍では、貨物の「オーバーブッキングポリシー」が例としてあげられています。
最近だと、飛行機のオーバブッキングポリシーが話題になりましたね。
(http://www.sankei.com/wired/news/170413/wir1704130001-n1.html)
キャンセルを埋め合わせるため、何%か予めオーバーブッキングしておくというものですが、これは「貨物」(サイズ)と「運行」(積載量)の2つのオブジェクトが関わります。
そこで「オーバーブッキングポリシー」クラスを作ることで複数のクラスにまたがる制約を表現しています。
プロセス
ここでいうプロセスはオブジェクトを取得して→Validationして→DBに格納する・・・といったプロセスではなく、9章の最初の例であったような、「荷受け地と荷出し地から輸送日程を割り出すプロセス」といったドメインに関するプロセスのことです。
9章の最初の例のように「経路選択サービス」クラスを用意するか、12章で説明されるストラテジーパターンを使うのも方法としてありそうです。
リファクタリングから「制約」「プロセス」を導き出す
書籍には無い内容ですが、制約とかプロセスといった概念的なオブジェクトはドメインエキスパートとの会話から出ることも多いですが、リファクタリングから導き出されることも多いような気がします。
「現場で役立つシステム設計の原則」の第2章では、「場合分けのロジックを整理する」リファクタリングの例がたくさん掲載されています。
ifの条件をメソッド化することで、それが制約として利用できたり、
料金クラスから子供料金、大人料金のクラスを作成して、それを使用して料金の合計を計算するプロセスを扱うクラスをシンプルにしたり、
JavaのEnumを利用して状態遷移のプロセスを表現したり、
暗黙的な概念を表すやり方がとてもわかりやすいので、お勧めです。
また、4章でも業務ルールの整理の仕方がわかりやすく解説されています。DDD本の9章を読む際には、「現場で役立つシステム設計の原則」も読んでおくと理解が深まると思います。
明日は「仕様」を読みます。