Fellow developer David Linsin wrote a blogpost about validation of domain objects recently. I actually wanted to leave him a reply but it got kinda long so I decided to post it here. So this is what came to my mind:
Prototyping some web portal kind of software I’ve encountered a similar situation. Take a User domain object as example for this problem. I decided to have a domain object as well as DTOs for maybe different clients. Why did I decide to do so? Well, the example beautifully shows what is a client specific vie on domain data. To edit the user on a web frontend (no matter if you want to create a new user or edit an existing one) you mostly let the real application user enter a password twice to ensure he enters the one he really wanted to enter. Nevertheless I of course don’t want to extend my domain object to hold a second password field, just because one single client needs it.
Another thing is registration of new users. I might want to ensure unique email addresses as I don’t want to have two users sharing the same mail address (whether this is a good idea or not).
What has this to do with validation. First of all I realized that validation is a client specific thing to a given extend and cannot be restricted do domain objects. Thus the decision to have DTOs the client technology specific exporters (an MVC controller, a WebService Endpoint a.s.o) handle and validate.
In consequence this means that my DTOs are “userfriendly” taking user form input as it is given. They are validated by external validation classes (maybe nicely separated into a hierarchy to avoid implementing common validation logic twice but allowing client specific validation logic where necessary). These also ensure the identity of both given passwords e.g. or the uniqueness of the user’s email address.
My domain objects are much more restrictive then. I tend to reject as much invalid input as possible. An email class definately would reject an invalid email string with an
IllegalArgumentException. Doing so in a DTO would make clean error messaging almost impossible.
As the validation subsystem or layer is allowed to depend on the domain layer I try to use eventually exposable validation logic from the domain layer. The regular expression to reject invalid email addresses in the email domain class could be used to nicely capture and reject the email field on the
UserDTO in an Spring MVC validator implementation.