LESSON 8.3
Specification
Recombine business rules into modular, composable predicate objects using boolean algebra: And, Or, and Not.
6 min read
Business rules are frequently scattered across controller validations, repository SQL WHERE clauses, and domain service checks. If the rule for "Eligible for Promo Discount" is coded directly into an if condition in the cart controller, you cannot reuse that exact same rule to query eligible customers from the database, nor can you compose it with other promotions dynamically.
The problem
// Scattered, rigid validation logic:
function isEligibleForPromo(user, cart) {
// If rule changes (e.g. min spend changes to $100), we must find and edit
// every place where this condition was copy-pasted across the app.
return user.isVip && cart.total > 50 && !user.hasOverdueInvoices;
}The pattern
The Specification pattern encapsulates a business rule into an object with a single method: isSatisfiedBy(candidate). It provides combinators (and, or, not) so rules can be assembled like building blocks.
The intent: Recombine business rules into modular, composable predicate objects using boolean algebra.
In code
When to use it, and when not to
Use Specification when:
- You have complex business validation rules that must be combined in different permutations.
- You want to reuse the exact same validation criteria across in-memory domain validation, repository database queries, and UI warnings.
- You want to keep domain entities clean from sprawling conditional code.
Don't use Specification when:
- You only have a single, straightforward validation check (e.g.
user.age >= 18).
Where you have already seen it
In Java Spring Data JPA, org.springframework.data.jpa.domain.Specification allows dynamic generation of SQL WHERE clauses by combining Predicates. In C#, LINQ expressions (Expression<Func<T, bool>>) compile specifications directly into SQL queries via Entity Framework. In validation libraries like Zod or Joi, schema chaining (z.string().min(5).email()) mirrors Specification composability.
Related patterns
- Specification vs Composite: Specification combinators (
AndSpecification,OrSpecification) form a Composite tree of predicates. - Specification vs Strategy: Strategy replaces an entire algorithm; Specification is a reusable predicate defining business policy.
Try it
Coupon Rule Engine LLD
Build a composable coupon specification engine that validates expiration dates, minimum spends, and user tiers.