Domain Driven Design has this notion of a Specification. The term is actually pretty self-explanatory, but here's what Eric Evans means:
... explicit predicate-like VALUE OBJECTS for specialized purposes. A SPECIFICATION is a predicate that determines if an object does or does not satisfy some criteria.
My understanding of a Specification is enforcement of your constraints and thus guarantee of a well-defined state of your domain objects. The most interesting idea is that the responsibility of validation lies within the domain layer. There are no service objects, containing validation logic, instead you add behavior to your domain model.
If you have a services layer, which provides various interfaces with a variety of technologies, you should make sure that your domain objects, which are passed in, are being validated before processing them. It's likely that there are consumers of your services, which can sometimes guarantee a well-defined and valid state of domain objects and sometimes not - depending on their characteristics.
Let's say you have a rich client, consuming your services. You probably want to perform validation before you call out to the server. In case of an expensive validation you potentially take some load of the server and avoid a roundtrip. Since you want to have the same service interfaces for different client technologies you either end up conducting validation on multiple levels - on the client and the server - or you discount the advantages of the rich client and only validate on server-side.
I tend to go with multiple validation and have a rich client validate before going on a roundtrip, but I'm not sure if this will work out as expected. There must be validation before having the server processing domain objects which were passed in. There is no way around that, only if you feel suicidal. One thing that you should avoid is duplication of validation logic. I think sticking to the DDD notion is crucial, because it helps maintaining and testing logic at a single spot in your code.
9 comments:
Hey David,
one more time nice topic. I guess we should go to drink a beer to discuss some of our thoughts now and then. ;)
I actually wanted to reply here but the answer got kinda long. Check out this one on that topic:
http://www.olivergierke.de/wordpress/2008/08/11/validating-domain-objects/
Regards, Ollie
Hi Ollie,
we definitely should go for a beer, especially after your post...I have a couple of questions :-)
The general answer is "It depends." You need to answer numerous specific questions before you can decide. e.g. How much do you trust comunication from the client, and what is the downside risk if your trust is misplaced? Do you want to lock your domain/service tier into talking only to that particular client tier or require each new client tier to do the same validation logic (you may if you'll always be accessing the functionality via an RIA)? How long do you expect the app to live/be maintained, and what is the skillset of those who will likely be maintaining it (it probably won't always be you because you will move onto better things).
Generally, I prefer dual validation in the scenario you describe because the downside of trusting the client is usually too great to tolerate (financial apps).
Validation is a very general word and applies to many different aspects of an application.
There are few hard, fast rules. If your domain itself is indeed strictly limited, validation can be done within the domain object itself -- for example, if your domain object is a Widget and a widget has a serial number that needs to be an 8-digit sequence with a checksum, then the setter method of that object can be used to detect invalid serial numbers.
However, consider the same object being used in multiple systems where some systems have the serial number rule but other newer ones use a different serial number method. Well now your serial number validator is no longer looking so good.
I typically make validation service on the back-end. Validation objects are created to filter inputs to the system and they can be plugged in via configuration. Front-end typically allows some duplicated effort for validation, though there are frameworks that attempt to reduce the actual duplication by creating a common validation space across both the front-end and back-end.
Considering how you will validate data going in and out of your system is an important architectural decision and one for which there is no one-size fits all answer.
Good luck to you!
anonymous > How much do you trust comunication from the client
I think in a service oriented environment you cannot trust anyone. It might sound pathetic, but the number one rule for not having your data screwed up is: Don't trust user input!
dantelope > However, consider the same object being used in multiple systems where some systems have the serial number rule but other newer ones use a different serial number method. Well now your serial number validator is no longer looking so good.
That's a very good point dantelope! I think you cannot open up your domain model to every client, but you have to come up with some kind of domain model for each service - some kind of dto. I guess that's what Ollie's is saying in his blog.
Hi David
Interesting post as always. Just read an article about catching checked exceptions and one of the commenters describes "his" way to validate business objects that I really like: http://gen5.info/q/2008/07/31/stop-catching-exceptions/#comment-639. He validates his business objects against a set of business rules (these could be configured via Spring for example, I guess). For each failed test he grabs the appropriate error and stuffs it into a BusinessException which is propagated back to the caller. It contains each violation of a particular business object which then may be presented to the user for example. IMHO, that's a really interesting way to do things. What do you think?
Ciao, Martin
P.s.: Already registered for Javapolis aka. Javoxx? ;)
Martin > For each failed test he grabs the appropriate error and stuffs it into a BusinessException which is propagated back to the caller. It contains each violation of a particular business object which then may be presented to the user for example. IMHO, that's a really interesting way to do things. What do you think?
Hi Martin! Thanks for the comment and especially the link. I'm already signed up for Javoxx 08, how about you?
The approach described is actually very close to DDD's Specification, if I've understood Eric Evans correctly. I like it a lot, especially the part with adding all failed validations to the Exception! I think I'm gonna implement that tomorrow :-)
Hey David
>> I like it a lot, especially the part with adding all failed validations to the Exception! I think I'm gonna implement that tomorrow :-) <<
;) I like this approach as well and will try it out as soon as I get the chance. Have you played around with it yet?
I've unfortunately not yet read the DDD book; I'm thus not familiar with the concept of a Specification.
>> I'm already signed up for Javoxx 08, how about you? <<
I will this week ;) Hope it's gonna be as good as last year!
Ciao, Martin
Great blog you have hhere
Post a Comment