集約とトランザクション境界に関するメモ
この記事はドメイン駆動設計 #1 Advent Calendar 2018の22日目です。
昨日は@crossroad0201さんによる「DDDの構成要素とマイクロサービスの単位をどう合わせるべきか」でした。
今日はエリック・エヴァンスのDDD本に書かれたパターンの一つである集約について、自分なりのまとめを書いてみたいと思います。実は以前まで集約については「言いたいことはわかるが実践で使う意義がいまいち見いだせない」というスタンスだったのですが、最近になってようやく腑に落ちました。
バートランド・メイヤーの契約による設計
DDD本のパターンの多くは、オブジェクト指向プログラミングで築かれてきた理論や原則に基づいたものです。OOPの理論で特に有益なものの一つに、契約による設計というものがります。これは鈍器としても名高い『オブジェクト指向入門』*1の著者であるバートランド・メイヤー博士が提唱したもので、簡単に言えば以下のような設計スタイルのことです。
- クラスは、そのインスタンスがライフサイクルの間、常に守らなければならないルール(クラス不変表明)を持つ
- クラスの利用者は、あるオブジェクトのメソッドを呼び出す時、そのメソッドが正しく働くための前提条件(事前条件)を守る義務がある
- メソッドは事前条件を守って呼び出された限りにおいて、予め定められた契約(事後条件)を守る義務がある
- オブジェクト生成命令(コンストラクタやファクトリメソッド)及び、コマンド(副作用のあるメソッド)は、クラス不変表明を守る義務がある
このスタイルを守ることで、プログラムが想定通りに動かなかった時にどのコードが契約違反を犯したのかが明白になります。また、プログラム言語によってはアサーションという仕組みを使うことで、契約違反の発生を即座に検出することが可能です。これを使うと問題のあるコードが実行されたまさにその場所でアサーションエラーが発生するので、バグの原因調査が著しく楽になります。
この辺りの要点は、@t_wadaさんがスライドにまとめられています。
【改訂版】PHP7で堅牢なコードを書く - 例外処理、表明プログラミング、契約による設計 / PHP Conference 2016 Revised - Speaker Deck
続きを読む