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