views:

199

answers:

3

Validation of Business Objects is a common issue, but there are some solutions to solve that.

One of these solutions is to use the standalone NHibernate.Validator framework, which is an attribute-based validation framework.

But I'm facing into conceptual concern. Attribute validators like NH.Validator are great but the validation is only performed when save-update-delete within the Session.

So I wonder if business objects should not be self-validated in order to maintain their own integrity and consistence?

+4  A: 

It's not always possible for them to self-validate though. What if you enter an "invalid" Zip Code? You could validate that the Zip Code needs to be in a specific format, but what if you want them to be "valid", that is "existing and matching the city"? Or what if you only accept phone numbers from certain area codes, and the list of valid codes is in a database maintained by the legal department?

If you can perform semantic validation, that's great and could go into the Business Class. But often, you might need extra validation that is simply not possible to handle by the business class itself but needs to be handled by the class that talks to the database and other external services.

Michael Stum
+1 You are right. In my explanation, I talk about validations that can be self-checked by the entities.
Javier Morillo
I agree. I prefer to keep my validation logic separate from by business entities.
Steven
+1  A: 

I don´t know if we are talking about the same idea, but if we are, I like what you explain. Very quickly, I´ll explain what I do to solve this. In my case, all the bussines objects in my domain layer must override two methods:

Obviously, to maintain this, I have more classes implicated, but I´ll not write all here, cos I´m only trying to explain the concept

List<ValidationRule> notPassedValidationRules = new List<ValidationRule>();

//...

public override void ValidateErrorsWhenSaving(Validator validator)
{
    //...
}

public override void ValidateErrorsWhenDelete(Validator validator)
{
   //...
}        

In these methods, I check for some boolean conditions, mantaining a collection of non passed rules. In my case, these methods are invoked before my Unit Of Work commits the changes (inserting new entities, updating, deleting), and show possible errors to the user, before commiting.

Javier Morillo
+4  A: 

IMHO - there are 2 steps of validations needed for a Business Object (BO)/Entity to be valid:

Step1: BO/Entity self-validation - In this, we check only if the entity is valid in terms of its state F.Ex.: If postal code is set, then does it have valid characters & is of valid length etc. form the BO/Entity level validations. But beyond this level of validation, we would not be able to say that the BO/Entity is valid in your business domain and/or repository. Typically the BO/Entity would be able to enforce this level of validation.

Step2: Context validation - In this, we need to validate if the BO/Entity is valid within the context of the Repository where it is being persisted. F.Ex.: Is the postal code valid for the country in which the order is being placed/sent to etc. For this validation, some or all entities in the current context might need to be involved to make sure the BO/Entity is valid.

So, to keep the entities pure, you will need to split the validation into these 2 steps - one performed by the entity itself & the second by the repository which is persiting/working with the entity.

HTH.

Sunny
This separation of the two steps is an interesting one. While I never really thought of it this way, I partially use this approach without knowing. Still, I try to also separate the self-validation from the entities. I explained how I did this with Validation Application block here: http://stackoverflow.com/questions/2258513/validation-framework-in-net-that-can-do-edits-between-fields/2259062#2259062.
Steven