views:

609

answers:

4

Hello, I've been reading Pro ASP.NET MVC Framework, Steven Sanderson, and in chapter 11 it discusses data validation.

On page 390 we see the section Moving Validation Logic into Your Model Layer. In this section we see, in page 392, some code showing how to implement validation.

The code implements a GetRuleViolations() method and the Save() method uses it to throw a RuleException if something was not alright.

It looks to me, however, that there's no distinction between the Domain Layer and a Data Access Layer, here's the code:

public void Save() {
    var errors = GetRuleViolations();
    if (errors.Count > 0)
        throw new RuleException(errors);

    // Todo: Now actually save to the database or whatever
}
private NameValueCollection GetRuleViolations() {
    // validations...
}

In a project I'm working, I have a Domain layer, as persistence-ignorant as possible, and a Data Access layer, implementing data access through NHibernate, and implementing the repositories which interfaces were defined in the Domain layer.

If I implement the validation rules as the author proposes here, on the "Save()" method, they would go on my Data Access layer, although, at least I think, they should reside on the domain model!

So, my question is: when creating a layered application, with a Domain layer implementing the domain entities and exposing interfaces to repositories (persistence ignorant), a Data Access layer implementing the repositories from the domain layer and implementing all the data access code, where should the validation rules reside?

My primary (or at least first) interface will be an ASP.NET MVC application, if that might change anything.

Thanks.

A: 

They definitely belong to your Domain Layer (where you could implement IDataErrorInfo, but that would only be useful for Windows Forms or WPF applications I think).

It looks like this validation philosophy is very similar to the one exposed by Paul Stovell (check out this article of his). It is very powerful and I use it a lot. Basically :

  1. There is nothing wrong with having an invalid business object, so long as you don't try to persist it.
  2. Any and all broken rules should be retrievable from the business object, so that data binding, as well as your own code, can see if there are errors and handle them appropriately.

So, as ignorant as your Domain Layer is of persistence matters, I believe your entities should be at least aware of when they are being persisted. The Save method is a way to make them responsible of their own persistence (that they can subsequently delegate to a Data Access Layer). I can't see anything wrong with this.

Mac
A: 

I usually prefere always valid domain objects. Domain objects can only be changed by methods that prevent the object to become invalid.

On the other side, the presentation objects can contain temporary invalid values, or values that cannot be parsed correctly. But methods calls will only be issued to domain objects by the presentation layer when the data is valid.

Domain objects enforce invariants, presentation objects indicates to user how it should modify its input to respect constraints.

Think Before Coding
+2  A: 

In an MVC architecture, the M (model) includes both the domain layer and data access layer. So there's nothing wrong with Sanderson's example.

That said, when you implement your domain model using both these layers (instead of having only one), validation logic should go to the domain layer to increase the cohesion of domain objects and avoid validation logic to duplicated in many places (e.g. in each concrete repository).

Buu Nguyen
I agree, but what about "contextual validation"? For example, the domain objects are valid, they are ready to be persisted, BUT there's a rule that says if a red car is visible through the user's window, then he is not allowed to save the object. This rule carries context information about the place/time of the *saving* operation. This information would come from a service that gives a list of all nearby parked cars (ie, something not in your project). Where would this validation rule be enforced, and yet follow a DRY principle?
Bruno Reis
In the service's method that performs the saving. I usually have these layers in my ASP.NET MVC apps: Controller --> Service --> Repository. Domain objects are used across these layers. Service (not controller) should trigger validation in domain objects. Contextual validation is then performed by the service before, say saving the domain objects. All these things (e.g. Service, Repository, and domain objects, i.e. Entity) are concepts of Domain-Driven Design. Why DRY? E.g. you can reuse all these (Services, Repositories, and Entities) in a WebForms app without a change.
Buu Nguyen
A: 

The validation should be done in your domain layer. Your business logic is part of the domain, not the data access. The validation may not be done inside of the domain object itself (the actual class), but it should live inside of the domain layer.

J.R. Garcia