What is the specification pattern?
Quick Answer
The specification pattern packages a business rule or query predicate as an object with an IsSatisfiedBy(entity) method (or a translatable expression), so it can be reused both for in-memory checks and for filtering a query, and combined with And/Or/Not instead of being duplicated as scattered ifs and LINQ Where clauses.
It's a way of turning a business rule into a first-class object instead of scattering it as inline conditions everywhere. A specification exposes something like IsSatisfiedBy, or in .NET more usefully an Expression<Func<T,bool>>, so the exact same rule — say “is this order overdue” — can be reused to filter an EF Core query, translated straight into SQL, and also reused to validate a single in-memory object. You compose small specifications with And, Or, Not to build up more complex eligibility rules, each piece named and independently testable, instead of one giant repeated LINQ predicate or a pile of duplicated if statements.
- Typical shape:
class OverdueSpecification : Specification<Order> { public override Expression<Func<Order,bool>> ToExpression() => o => o.DueDate < DateTime.UtcNow && !o.IsPaid; }. - Because it's an
Expression, EF Core can translate it into SQL — the same specification runs as a database filter, not just an in-memory check. - Combinators (
And,Or,Not) let you build complex eligibility rules from small named pieces that are individually testable. - Worth the ceremony when the same business rule is checked in multiple places (a query filter, a validation, a UI enablement rule) and needs to be named and tested once.