Hi,
I know exactly what you're talking about regarding patternitis 🙂
There's also it's not so distant cousin "Analysis Paralysis". Where you sit there designing and redesigning trying to apply new methods you've learnt and not getting anywhere.
To do this with a dataspace object we would end up with something like the following, am I right?
yes you are correct 🙂
$rule = new Rule();
$rule->setType('string');
$rule->setCode(2);
$rule->setMaxLength(20);
$rule->setMinLength(6);
$rule->setRequired(true);
$rule->setSpecialCharacters(true);
$validator = new Validator($rule);
What I'm missing here is this. What is the advantage of this method over the following.
$validator = new Validator();
$validator->setType('string');
$validator->setCode(2);
$validator->setMaxLength(20);
$validator->setMinLength(6);
$validator->setRequired(true);
$validator->setSpecialCharacters(true);
When you need to create different rules for different input.
You could use the Rule object mentioned above as a Concrete class would have been a base object. You could superclass the Rule class with String_Rule(), Password_Rule(), Email_Rule(), Numeric_Rule() or any other rules that your input would need to follow.
Actually, I think I understand. Is the reason for this to prevent Validator being in an invalid state? We have mandated that Validator must have the following fields set in order to be valid. Although, one thing which still doesn't sit right with me is the potential for duplication. We now have two sets of setter methods, one in the Rule class and one in the Validator.
You're looking at the validator differently from how I'm seeing it. I guess my reason main reason is actually going back to the base principle that an object should do one thing and one thing well.
A validator's role is to check if input matches certain criteria/rules. It has one action - validate and returns true or false.
If the validator owns the criteria (whether it be through composition or having rules as its attributes) instead of using it, then it would either be inflexible, or be a god-ish class.
You'd be instantiating a validator with methods to set email, string and numeric rules/criteria you've set when all you wanted to do is validate a password field.
So off the bat let's think about this one, well, let's separate them... A validator for different types with the common functionality in a base validator object.
Base_Validator,
Email_Validator,
Custom_Validator,
Numeric_Validator,
String_Validator
At this stage, it kind of feels better, but still doesn't feel right, we're going to be making a validator for each field, we're going to be setting the criteria for each validator. That's going to be pretty strenuous if we were to validate 4/5 fields.
If we take another look at it, the validator base class would only ever have the 1 public method and a bunch of protected methods for handling criteria checks.
Let's super class the validator and add your accessor and mutator methods for each type of validation you need.
Taking a closer look at it, all we doing here is specifying criteria. We are creating validators so that we can specify criteria for the validator.
You should start sensing that this is the perfect time to quote the words "Composition over Inheritance" ... right... if we apply it to this case, that's going to be a nightmare... How about... "Aggregation over Composition".
Let's make our Base Validator class a generic concrete class. The Validator will only concern itself with Validation and use a private set of methods to make comparisons. Maybe you can decompose this a little further later on if the types you're handling explodes to a bad number.
Now then, onto the rules that the Validator will read. In the previous examples you and I have used, we have to manually set the values for criteria. What if we had default criteria that are mutable for each rule? Like say our string rule can have 20 characters as its default value.
we could have implementations like:
$validator = new Validator();
$validator->validate($this->_request->get('username'), new String_Rule());
$validator->validate($This->_request->get('password'), new Password_rule());
I'm slowly coming around to the reasoning for this pattern but I'm still not convinced. If you have the time, please convince me 🙂
Although I mentioned "DataSpace", my point is actually outside the scope of patterns, my point is geared more toward encapsulation/abstraction of application complexity rather than a "Use this pattern now Now NOW!" recommendation.
Apologies if I came accross like so, and also, I'm not trying to convince you, I made the posts that I have because I enjoy discussing this stuff. So don't feel like I'm bullying you into seeing things the way I do 😉
ps. I'm sorry it's a little vague, it's 4 am here!
regards,