Domain modelling made functional Chapter 6, Chapter 7を読む

Domain Modeling Made Functional: Tackle Software Complexity with Domain-Driven Design and F#

Domain Modeling Made Functional: Tackle Software Complexity with Domain-Driven Design and F#

6章では集約などの一貫性をどう表すか、を重点に置いて話を進めていっている。ここでも型として表現していくことを徹底している。例えばビジネスルール上で「顧客はemailか住所を持っていなければならない」とした時に、どう表現するか? この本の回答はこうだ。

  • emailのみの情報を表現する型
  • 住所のみの情報を表現する型
  • emailと住所の情報を表現する型

これらの型の'OR' Typeが顧客が持つ情報であるとしている。こうすることによって、ドメイン上でありえない状態に陥ることがなくなる。型で表現することによって、そもそもillegalなことを表現させなくするという観点は非常に面白いし、自分の頭からは抜け落ちていた観点だったと気付かされた。

またDDDの文脈でよく出てくる集約の一貫性の話、単一の集約や複数の集約間の整合性はどうするかなども書かれているが、やはり基本として「1集約に1トランザクション」「結果整合性」という話になる。この部分はまあそうだよねという気持ち。

7章はワークフローをパイプライン処理できるよう個々の関数に落とし込んでいく。入力であるCommandをGenericsを用いて表現したり、MQに単一のCommandだけでなく複数のCommandが入る場合は型としてどう表現するかなど、見所は多い。が、ここではこれまで定義してきたそれぞれのOrderを状態として捉える、UnvalidatedOrderが処理されることでValidatedOrderになりまたそれが処理されPriceOrderになる、一連の流れを状態の変化として考えることが重要な点だろう。型によってState Machineを表現することによって、抜け漏れなくある状態である動作を行うことができるようになる。実際にどでかい状態遷移図で悩まされたことのある自分にとっては、ありがたさがよくわかった。

後半では、副作用を表現していったり長期間にわたるワークフロー*1についても書かれている。副作用を型として表現する話は過去にScalaMatsuriで聞いていたのですんなりと納得できた。本書中の例としても途中のValidationを行う関数がリモートサービスを呼び出しているので、それを呼び出してる関数もreturnとしてはAsyncResultにならないといけない、とわかりやすい。Sagasは最初さらっと読んでいたが、今考えてみればAkkaなんかを使う局面と考えても良さそうだ。

ここまでで、一旦モデリングは終わり。8章からは実装の話に移る。

*1:Sagasと呼ばれる