This project is read-only.

Task (aka DomainServices) Layer Validation

Jan 6, 2010 at 11:43 PM

Hi All,

I was hoping to get a discussion going regarding the best way to do Validation on the DomainServices and Framework layers, based on the implementation in the WCHM sample app.

In WHCM.Tasks.ProfileTasks, we have the following CreateProfile method:

        public void CreateProfile(CreateProfileDetails createProfileDetails)
        {
            createProfileDetails.Validate();

            var profile = new Profile {
                                          UserName = createProfileDetails.UserName,
                                          FirstName = createProfileDetails.FirstName,
                                          LastName = createProfileDetails.LastName,
                                          CreatedOn = DateTime.Now.Date
                                      };

            try
            {
                this.profileRepository.Save(profile);
            }
            catch (Exception)
            {
                // Catching DB unique constraint violation and converting to validation error
                // Should use nhibernate sql exception convertor to do this properly
                throw new RulesException("UserName", "User name already exists");
            }
        }

In terms of validation, there are two types/cases we are interested here:

1) Ensuring that the model (createProfileDetails) is in a valid state

2) Ensuring that other validation rules are met (in this case, there is one: the "Unique UserName" rule) to perform the action ("Create Profile")

 

The first case is ensured by calling the .Validate() extension method.

The second case is ensured by catching the necessary NHib exception from the repo.

 

I think the flow of this (domain) service method is great (assuming that the TODO note inline was fulfilled). My question is about the architecture:

Do you think it's OK to depend on xVal here? More specifically:

* WCHM.FrameWork.Validation.ValidatableExtensions.Validate() (ie, the Framework layer) throws a xVal.ServerSide.RulesException when the model is not valid

* WHCM.Tasks.ProfileTasks.CreateProfile() (ie, the Tasks layer) throws a a xVal.ServerSide.RulesException when a business rule is not met

 

To me this seems a bit iffy, but I'm open to being convinced :)

My inclination would be to rely instead on some kind of type in SharpArch.Core (.CommonValidator?) in the Tasks and Framework layers, and do some kind of translation to xVal stuff on the Web/Web.Controller level.

What do you think?

 

As always, any input is greatly appreciated.

Best regards,

Martin

Jan 15, 2010 at 1:46 AM

Looking at the validation further, I have some additional questions/comments.

 

In terms of flow, we see:

 

* View takes a ViewModel decorated with NHibernate.Validator attributes. xVal uses this model on the client side to do it's work (e.g. CreateProfileViewModel)

* Controller takes the ViewModel (e.g. CreateProfileViewModel) and maps it to a domain "command object"/entity. (e.g. CreateProfileDetails). The domain entity is also decorated with NHibernate.Validator attributes

* Controller passes command entity to the Tasks layer (e.g. UserTasks.CreateProfile()).

** The Tasks layer method first makes sure that the entity is in a valid state. It does this by calling the Validate() extension method, implemented in the Framework layer. In the Framework layer method, if validation fails, an xVal RulesException is thrown.

** The Tasks layer method then makes sure that the intended operation is valid by conducting other business logic - if any test fails, and xVal RulesException is thrown

 

In terms of dependencies per layer, we have:

* Web/View

** xVal for client side validation

** NHibernate.Validator to mark ViewModels with validation attributes

 

* Controllers

** xVal for server side validation

** xVal RulesException to orchestrate operations

 

* Tasks

** xVal RulesException to orchestrate operations

 

* Framework

** xVal RulesException to orchestrate operations

 

* Domain

** NHibernate.Validator to mark up domain "command object" entities with validation attributes

 

 

I think the dependency in the Domain layer and View layer on NHibernate.Validator is acceptable, as this is the chosen validation framework.

My concerns are:

* Validation rules must be duplicated: on the ViewModel model and on the Domain "command object" (both using NHibernate.Validator attributes)

* The Tasks layer depends on xVal to orchestrate operations

* The framework layer depends on xVal to orchestrate operations

 

The latter two points are restating the same questions raised in my previous post.

 

Mind you, I don't have a clear understanding of whether there is a better way of doing this. Instead, my intention is to solicit comments on the setup, and have the more experienced members of the community provide their insight :)

As always, any feedback would be greatly appreciated. Thank you in advance for your time!

Jan 15, 2010 at 2:39 PM

I have a lot of the same questions actually. This is a subject that is very hard to find a definite answer to. A search on the S#arch mailing list shows endless threads.
http://groups.google.com/group/sharp-architecture/search?group=sharp-architecture&q=validation

The answer to your concern is, it depends on your project. But I share your thoughts, in a few weeks I will rewrite the current validation system in the project I'm working on and try to address some of your questions. I hope I will come up with something I can contribute to sharp.

Also, MVC2 comes with some promising news http://weblogs.asp.net/scottgu/archive/2010/01/15/asp-net-mvc-2-model-validation.aspx

Jan 15, 2010 at 8:56 PM

Hi bondehagen,

Thank you for the comments. I look forward to your contributions!

 

As for the validation stuff in MVC 2, it's cool, but it's also what xVal has been doing for MVC1 for quite some time. In fact, xVal still has some added benefit compared to the MVC2 stuff, like custom client side validators.

For WCHM or SharpArch, it will be one of the architectural decisions that will need to be made when adopting MVC2. I suppose this decision will also depend on what happens to xVal (whether or not active development will continue).

Another architectural decision that may have to be made concurrently is how validation will be supported in the Model/Domain layer. An interesting question will be whether SA will continue to take a dependency on NHibernate.Validator, or adopt a pluggable validation setup, where domain validation frameworks can be swapped (to DataAnnotations, for instance).