intro
The specification pattern is something my team has studied and used effectively in various projects to handle changing policies/rules. In this article, I’ll introduce what the specification pattern is and how things can change before and after applying it.
What is the Specification Pattern?
The specification pattern in object-oriented programming allows you to concisely express specific rules about a domain. It separates rules from conditional logic implemented inside the domain, making the rules explicit. If the conditions are simple, there’s no need to separate them, but as business requirements are added, rules can be varied and combined in many ways beyond the original purpose of entities or value objects. At this point, you create a specification separated as a predicate that determines whether an entity or value object meets specific criteria.
| |
To express rules, you implement multiple Specifications and logically combine predicates with operators like and, or, not to indicate whether an object meets certain criteria.
What I mean by combining predicates - using performance entry policy as an example
| |
→ Like isEntryAllowed, it means representing each detailed condition as a combination of concrete Specifications that implement the Specification interface.
.
Example
Just explaining might not be very impactful. Let me give an example of how specification becomes useful in a specific situation. (I took an example from the ‘Domain-Driven Design’ book and added some flesh to it.)
Assume in a payment domain that issues invoices, you check customer delinquency information and send emails. There are two conditions for determining whether to send an email:
- When today’s date exceeds the invoice due date + grace period combined
- When the unpaid amount exceeds $100
Before Applying Specification
When creating a method to judge conditions inside domain objects without using the specification pattern, you can write code like below.
| |
Client code for email sending that uses domain logic is written with conditional statements for the judgment conditions.
| |
So far it doesn’t look too bad. But what if new requirements are added after deploying to production?
- Z-type Invoices should not send emails
Add a method to Invoice and add a judgment condition. I added line breaks for readability.
| |
If another requirement comes in a few days later…?
- Among delinquent users, customers with delinquent amounts exceeding $4000 should receive emails with a different template.
It can be implemented in various ways, but roughly it would be code like below.
| |
With just two requirement additions, the code readability has already dropped significantly. As other requirements increase and conditions multiply, you have to think about where to insert them while following existing code logic. Invoice object methods will have more methods for conditions to determine rules than the Invoice object’s original responsibility.
Applying Specification
How does it change when using specification?
Requirements
- When today’s date exceeds the invoice due date + grace period combined
- When the unpaid amount exceeds $100
Create Specification implementations for each.
| |
And to combine the two conditions with and, create an And Specification implementation.
| |
Client code for sending emails is expressed as follows.
| |
If you represent and like an infix operator, it can be expressed more like a sentence in human language. This is possible by implementing a default method in the interface.
| |
When adding more requirements here, the code can be written like this. Please overlook the variable names
- Z-type invoices should not send emails
- Among delinquent users, customers with delinquent amounts exceeding $4000 should receive emails with a different template
| |
When requirements are added, you can create them by reusing and combining existing Specifications. If you refactor the above code a bit more to make the client depend only on the InvoiceSpec interface, it becomes simpler and easier to write test code. For the various conditions declared as constants, you can separate them into objects that represent conditions and the results according to conditions.

.
Conclusion
Specification is not a pattern commonly introduced in the Gang of Four (GoF) design pattern book like composite or singleton patterns, so it was unfamiliar when I first heard of it. It’s a pattern developed by Martin Fowler and Eric Evans, described in chapters 9 and 10 of the ‘Domain-Driven Design (Eric Evans)’ book and in Martin Fowler’s paper. Fowler introduces this as both a design pattern and an analysis pattern (a way of capturing how people think about domains).
I’ll cover more detailed examples of the pattern from the ‘Domain-Driven Design’ book and actual uses in the next article.