I have read a few books on OOP DDD/PoEAA/Gang of Four and none of them seem to cover the topic of validation - it seems to be always assumed that data is valid.
I gather from the answers to this post ( http://stackoverflow.com/questions/1651964/oop-design-question-validating-properties ) that a client should only attempt to set a valid property value on a domain object.
This person has asked a similar question that remains unanswered: http://bytes.com/topic/php/answers/789086-php-oop-setters-getters-data-validation#post3136182
So how do you ensure it is valid? Do you have a 'validator method' alongside every getter and setter?
- isValidName()
- setName()
- getName()
I seem to be missing some key basic knowledge about OOP data validation - can you point me to a book that covers this topic in detail? - ie. covering different types of validation / invariants/ handling feedback / to use Exceptions or not etc
Source: Tips4all
In my experience, the validation occurs where there is human/user input. And this usually happens where you allow through your method to change something. In your example, I would go for validation for the method:
ReplyDeletesetName()
So It happens where you allow input of values/setting values which turns out to be setter methods.
Each object should make sure that its internal state is consistent, so validation is best done before the internal state is modified - in the object's setter methods.
ReplyDeleteIn short, always validate. In long, perform your validations all together at once, not 'along the way'. This will help your code remain streamlined and help debugging confusion.
ReplyDeleteIf you control the code that uses your class, then you should be validating before even attempting to manipulate the object's variables (through the public properties). If you are anticipating a scenario where you don't know how your class is to be used, then yes, you should validate within the property, that's more or less what they are for. Obviously this assumes the definition of "is a valid name" is a static business rule inherent to the object.
ReplyDeleteValidating on both levels is of course, the safest route to go.
This depends on your style of programming, as Wikipedia has more detailed explanations I will just scratch the surface and link to Wikipedia. (Yes, I'm THAT lazy. :-))
ReplyDeleteNOTE: All of this does NOT apply to user input. You have to validate it in either way. I'm just talking about the business logic classes which should not be coupled with the user input in any way. :-)
Defensive
As mentioned by others, you will enforce every property to its bounds. I often threw runtime exceptions (Java) to indicate those failures.
Wikipedia on Defensive Programming
By Contract
You document the requirements of your code and assume, for example, the values passed to your setters are valid regarding to the defined contract. This saves you a lot of boilerplate code. But bug hunting will be a little more difficult when an illegal value was given.
Wikipedia on Design by Contract
It's important to distinguish between valid in the sense of a domain object's invariants (which must always be satisfied) and what some people call "contextual validation." For example, is a customer with a negative bank account "invalid?" No, but they may not be authorized to perform certain kinds of transactions. That's contextual validation, in contrast to "every customer entity must have a non-null ID," which is a different type of validation altogether.
ReplyDeleteOne effective technique to enforce invariants is to distinguish classes that represent user input from domain objects and don't expose unrestricted mutators (simple set accessors, for example) on your domain objects.
For example, if you have a Student domain object, don't manipulate it directly in the user interface. Instead of creating Student instances, your views create StudentBuilder instances that model what you need to construct a valid Student domain object.
Next, you have classes that validate builder instances conform to the domain object's invariants, and a factories that takes accept builders and can transform them into valid domain objects. (You can also introduce contextual validation strategies at this step as appropriate.)
An important part of the OOP is too always keep your object in a valid state. Therefore, validation should be done after an input that could modify the object.
ReplyDeleteIt's always good to validate data comming from properties/set, parameters to functions and constructor.