Aspen – part 7 of X – Entity Validations
Dag König
and I had a meeting today about the Aspen project. We talked
most of the time about validations and how we should
implement it. I decided to post about the current decision
made.
Validation on Entity level
Sometimes it feels important to add validation to an
entity, for example a FirstName can’t have a size greater
than X characters etc. But is it important? The main reason
why such validation may be of interest is based on the
limitation set on the data source. The column FirstName in
the database is set to nvarhcar(XX). But should we really
add a validation like the following to the entity because of
that?
public class Member { private string _firstName; public string FirstName { get { return _firstName; } set { if (string.IsNullOrEmpty(value)) throw new ArgumentNullException("FirstName"); if (value.Length > 20) throw new ArgumentOutOfRangeException("FirstName", "FirstName can not have more than 20 chars"); _firstName = value; } } }
In real life a company will probably not lose any business
because of the length of the FirstName, so the domain model
in that case shouldn’t really care about doing the
validation, or?! The only reason the validation is there now
is because of the constraint added to the data source, but
it’s not a constraint for the business. In this case I think
that kind of length validation is not important to have in
the entity at all, it’s irrelevant for the business. I
prefer to not have that kind of logic into my entities,
instead I will let the data source throw an exception if the
chars exceeds XX numbers of chars. In this case the data
source will do the validation. Some of you may say “But by
adding the validation to the entity, there will not be any
database access, and that will increase performance”. That
is true. But how often will the FirstName really exceed the
XX numbers of chars? If we use a sophisticated ORM, we can
also specify in the mapping between the domain model and
database schema, the length of the field etc, and let the
ORM do the validation before it tries to persist the model.
nHibernate will do it for us, but I haven’t seen a way of
doing it with Entity Framework 4 code-only and I’m against
adding attributes to my entities. Will not make them a pure
POCO. One benefit by adding validation to the entity, would
be to prevent a developers for using the entity in a wrong
way. He/she will be notified early if the FirstName exceeds
20 chars. But I don’t think it’s up to the domain model to
care about performing validation based on a data source
constraint.
I will only add the above validation
if that is really a business rule.
Note: The empty string validation in the code is
important, if we don’t have a FirstName we can lose
business.
Should we always let the database handle the validation based on exceptions?
If we skip the length validation in our FirstName property,
the validation will take place by the database. It will
throw an exception if the FirstName exceeds the length of
the specified ncharchar(XX). So stupid, why should we do the
data access in the first place and waste some resources
others action can use instead? The answer is, we can do the
validation, but not on the entity level, more about that
later under the topic “User Interface Validation”. If we use
a sophisticated ORM, we can let it perform a validation
before the entity is persisted.
Rule based validation
There can be a problem by adding validations to the entity
or even to other parts of the domain model, for example to
the Repositories. Some specific validations can be based on
a specific business case or the context the entity is in. If
we add validation to the entity, the validation will always
take place but in one specific context that kind of
validation isn’t important and can stop us for performing a
specific business case. So instead of adding validations to
the Entity, we perform validations based on the context the
entity is in. The validation can for example take place in
service/application layer. This can be done in several ways,
for example in a simple method where the method will
validate the entity’s values. This is the approach we are
going to use. The following methods will do different kind
of validations of the member entity based on its context.
ValidateMemberBeforeRegisterTheMember(member); ValidateMemberBeforeUpdatingTheMember(member);
User Interface Validation
WCF RIA Services supports annotation validations, so
we can on our DTO for example add validation attributes to
properties. WCF RIA Services together with Silverlight
binding validation can perform validations on the
client-side, WCF RIA Services will also do the validation on
the server-side. So instead of adding validation such as
length validations to an entity, it can instead be added to
the Presentation layer and the Service layer. The following
is an example where the WCF RIA Services annotation
validation is used:
public class MemberDto { [Key] public int ID { get; set; } [Required] [StringLength(20)] public string FirstName { get; set; } ... }
Is someone succeeds to by pass the DomainService and
try to add entity, the database will throw an exception if
the length of the the FirstName exceeds for example 20
chars. How often will that happen. Well probably never, and
if it does, the database will to the last validation.
Based on our business case, we decide to not add
length or other kind of constraints for our entities. I
would really like to have your comments about this and what
solution you prefer to use.
If you want to know when I add a new blog post,
please follow me on twitter:
http://www.twitter.com/fredrikn