Implementing Domain Rules Pattern for Robust Applications
Now that we understand the difference between trivial validation and business rules, let’s see how we can implement a robust system to handle complex business rules.
I’ll try to show you how to implement business rules in a clear and maintainable way using a usual car sales system as an example. We’ll explore how to move beyond simple validation to handle complex business scenarios…
The Problem
Business rule validation is one of the most challenging aspects of implementation. We often start with simple checks, such as validating whether a price is greater than zero, only to quickly encounter complex business requirements that transform our initially clean code into a hard-to-maintain mass of conditional checks.
…and then business overwhelms you with rules:
- The price must be in the market value range ±20%
- Dealer must not sell luxury models
- Special price rules apply to certain regions
When Simple Becomes Complex
In trying to answer all these requests, we often end up with code that tries to solve all problems in one place. Here’s what it usually looks like in practice:
Solution as Domain Rules Pattern?
Instead of letting our validation logic become an unmanageable mass of if-statements, we can apply the Domain Rules Pattern. So, instead of mixing all the rules, let’s:
- Each rule should be a separate class
- Each rule has a clear reason for existence
- We can easily add/remove rules
The core of this approach lies in defining a clear interface that represents a business rule.
Each rule must say: am I satisfied (IsSatisfied) and if not, why (ErrorMessage).
Let’s define new rules:
Why Is This Better?
By using the Domain Rules Pattern, we can easily add new rules without breaking existing functionality. For example, when we need to implement special rules for fleet sales, we simply create a new rule without touching the existing code.
So, each rule is self-documenting:
- MarketPriceRule → market price check
- RegionalPricingRule → rules for regions
- DealerAuthorizationRule → dealer restrictions
As result we have better feedback. Instead of generic Invalid price, you get exactly what is wrong:
- Price is 30% above market value
- Dealer not authorized for luxury vehicles
- Price not valid for current region
You can test each rule independently:
For the end
This pattern transforms complex car price validation from a chaotic series of if-statements into clean, maintainable code. It’s flexible enough to handle new requirements, while still keeping the code organized and testable. The next time you’re building a system with complex business rules, remember to:
- Separate the rules
- Keep them explicit
- Keep them focused
Your future team will thank you!
Cheers and Good Luck! 👋