I'm discovering craftsmanship and trying to learn it, and I decided first to understand how to work with the SOLID principles.
I'm actually facing some troubles while dealing with the Open/Closed principle.
How I'm working
In fact, I'm usually building applications like the following:
- Presentation layer with Angular
- Business layer with Node.js (using service / repository)
- We abstract the DAL for now, just for learning purposes
Actually, I used to put my business rules in my services, using multiple if
and else
statements. But the fact is that I'm really open to modification but not to extension in that case. I want to change that, in a good and open way.
My rules
Let's take a simple example where in my application I have to collect a mail address that has to match the following business rules:
- The domain should be example.com
- The first part of the mail address should contain a "." like "firstname.lastname"
- The first part of the mail address should be less than 100 chars
How I tried to refactor my multiple if statements:
class BusinessMail{
checkMail(){
const ruleArray = []
ruleArray.push(new MailCheckDomain(mail))
ruleArray.push(new MailCheckLength(mail))
ruleArray.push(new MailCheckDot(mail))
for(const rule of ruleArray){
if(!rule.apply()) return false
}
return true
}
}
Right there, I'm leaving my if / else statements. But my mail checking function is really open to modification, because if I need to have a rule, I have to have it in my function body.
Another solution would be to inject my array into my service:
class BusinessMail {
constructor (mailRules = []) {
this.mailRules = mailRules
}
checkMail () {
for (const rule of this.mailRules) {
if (!rule.apply()) return false
}
return true
}
}
This way, I'm not forced to create my rules inside of my service.
But what if I have a big amount of stuff inside of this class? I mean, my business domain is really small in that case. But what if I have a service that has to check like 50 different rules, on different functions? It means that I would probably have to initialize multiple arrays of rules.
I don't feel good with this solution and I'm looking for something better if possible.
Does anybody know how should I do this to have my OP principle applied on my business layer without this feeling of "no trust"?