Explicit Constraints [明示的な制約] (220ページ) †
要約 †
- 制約はモデルの概念で特に重要なカテゴリを構成する。しばしば暗黙的になっているが、明示的にすることで設計を大きく進歩させることができる。
- 例えばBucketオブジェクトは、キャパシティを超えないという不変条件を保証しなければならない。簡単な実装では、内容の変化に対して条件ロジックを書くことで強制することができる。
public void pourIn(float addedVolume) {
if (contents + addedVolume > capacity) {
contents = capacity;
} else {
contents = contents + addedVolume;
}
}
- この例は簡単なためルールが明確だが、複雑になると制約を見失う可能性があるため、メソッド抽出リファクタリングを使い、メソッドに制約の意味を表す名前をつけることができる。
private float constrainedToCapacity(float volumePlacedIn) {
if (volumePlacedIn > capacity) return capacity;
return volumePlacedIn;
}
- どちらのバージョンでも制約を強制できるが、後者ではモデルとの関係がより明らかになっている。シンプルなルールなら前者でも問題ないが、ルールがより複雑な場合は適用対象のオブジェクトやメソッドを圧迫しはじめる。後者のアプローチを取ることで設計をより明示的にできる。
- また、制約は呼び出し元の操作より大きくなりがちだが、後者では呼び出し元が自身の責務に集中でき、シンプルさを保つことができる。
- 分離されたメソッドは、拡張する余地があるが、しばしば1メソッドには収まりきらないときがある。たとえシンプルであっても、本来のオブジェクトの責務には不要な情報を持つこともある。
- 以下3つが、制約がオブジェクトの設計を歪める兆候である。
- 1. 制約の評価の際に、オブジェクトの定義にはふさわしくない情報を必要とする。
- 2. 関連するルールが複数のオブジェクトに渡り、重複や、特に関係ないオブジェクト間で継承が強制される。
- 3. 制約をめぐって、多くの設計や要求の会話がなされるが、実装では手続き型のコードに隠されてしまう。
- 制約がオブジェクトの責務を曖昧にしたり、あるいは制約がドメインでは支配的だが、モデルでは表現されていない場合、リファクタリングで明示的にオブジェクトを作ったり、あるいはオブジェクトと関連のセットとしてモデリングしてもよい。
- 例:Overbooking Policyをもう一度見てみる
担当者のつぶやき †
私の作業が遅くなったせいで、編集が渡邊さんとバッティングしてしまいました。マージしておきました。
みんなの突っ込み †
- 制約をルールエンジン(Droolsなど)を使って実装することには意味があるでしょうか? -- 佐藤?