【スペシフィケーションパターン】

Specificationパターン とは?

💡 ビジネスルールを組み合わせ自在なブロックに——条件を部品化してパズルのように組み立てる
📌 このページのポイント
Specification パターン — 条件の組み合わせ PremiumMemberSpec isSatisfiedBy(user) InStockSpec isSatisfiedBy(product) AndSpec A.and(B) isSatisfiedBy true / false 同じSpecを複数用途で再利用 バリデーション DB クエリ条件 ドメインロジック 絞り込み検索
SpecはAND/OR/NOTで組み合わせ、バリデーションからクエリまで使い回せる
ひよこ ひよこ

ビジネスルールってif文で書いたらダメなの?

ペンギン先生 ペンギン先生

小さいうちはいいんだけど、ルールが増えると「プレミアム会員かつ購入歴90日以内かつ在庫ありの商品」みたいな条件がコードのいろんな場所に散らばってしまうんだよ。Specificationパターンはそれを解決するんだ。

ひよこ ひよこ

どうやって解決するの?

ペンギン先生 ペンギン先生

条件を表す「Specオブジェクト」を作って、isSatisfiedBy(candidate)というメソッドで判定するんだよ。たとえばPremiumMemberSpecを作っておけば、どこからでも使い回せるし、テストも独立して書けるんだ。

ひよこ ひよこ

AND/OR/NOTで組み合わせられるってどういうこと?

ペンギン先生 ペンギン先生

Specオブジェクト同士を組み合わせてandメソッドやorメソッドを使えるんだよ。たとえば「プレミアム会員」Specと「在庫あり」Specをandで結合すると、両方を満たすかチェックできる。SQLのWHERE句をオブジェクトで表現するイメージだよ。

ひよこ ひよこ

リポジトリパターンと一緒に使うことが多いの?

ペンギン先生 ペンギン先生

そうだよ。RepositoryのfindメソッドにSpecを渡して「このSpecを満たすエンティティを取得して」と指示するのが定番の使い方だよ。SpecをSQLのWHERE条件に変換するアダプターを書けば、クエリも共通の仕様で制御できるんだ。

ひよこ ひよこ

どんな時に特に効果があるの?

ペンギン先生 ペンギン先生

同じルールをバリデーション・クエリ絞り込み・ドメインロジックの3か所で使いたい場合にとくに効くよ。たとえば「有効なクーポン」の定義をひとつのSpecに集めておけば、画面表示・DB検索・適用判定すべてが同じSpecを参照できて、定義の変更が1か所で済むんだよ。

ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「Specificationパターン」って出てきたら「ビジネスルールをオブジェクトに切り出してAND/ORで組み合わせる設計手法」と思えればだいたいOK!
📖 おまけ:英語の意味
「Specification Pattern」 = 仕様パターン
💬 EricEvansとMartinFowlerが2000年頃に提唱したドメイン駆動設計のパターンだよ。「仕様(Specification)」という名前は、条件を宣言的に記述するという考え方から来ているよ
← 用語集にもどる