A lesson learned: FubuMVC.Validation

Lessons LearnedWhile creating the FubuMVC.Validation framework I messed up a couple times, which is a good thing because it gives me an opportunity to learn and improve myself. But what kind of developer would I be to keep these experiences to myself, a pretty selfish one I tell you. So here it goes:

How did I start.

It started with an idea that I wanted validation and that I didn’t like to have to use attributes for it, also looking at FubuMVC you may notice that it is a very opinionated framework where Convention over Configuration and Separation of Concern are kept in very high regards. So if I was going to create anything then it should at least be following these common rules.

I started thinking about the implementation and concluded that I wanted something that could be executed from a behavior and configured using an internal DSL very similar as how Controller actions are configured in FubuMVC.

So with that in mind I started creating tests that verified how I wanted my DSL to look like. I did this step by step, starting with a way to add default conventions to the validation configuration. I had already learned that in order to be able to properly us a DSL that you want to the DSL to configure a Semantic Model instead of keeping the entire configuration in the DSL itself. So my DSL was configuring my Semantic Model which conveniently I could use to verify that the configuration was stored properly. During this process I also created some basic validation rules like IsRequired, IsEmail and IsUrl which basically had an IsValid method that takes a string and returns a Boolean.

After this I started on a way to determine which view models should be validated and which should not be validated. Now considering that I wanted the validation to happen in a behavior I also needed a way to transfer the validation results to the controller. So I decided to create an interface “ICanBeValidated” to specify how these results are transferred to the controller. At the same time I could use this interface as a marker to filter view models that implemented this interface and thus could be validated by my validation framework. Now that I was able to identify the types that could be validated, it became very easy to automatically collect all the different view models from a given assembly and add them to the semantic model.

Then I needed a way to alter the validation rules for a specific view model, because I knew that it would be very unlikely that you could do everything via conventions. So I needed to be able to add and remove conventions from a specific view model. In order to be able to do this I decided that during the scanning of view models that could be validated I should also add the default conventions to each view model. This way I could alter one specific view model without affecting the others. I implemented the parts of the DSL that could alter / override the conventions of a discovered view models.

This was going great; I managed to completely create my DSL for configuring my validation framework using Test Driven Development (TDD) and thus had all the insurance I needed to know that this worked well.

So now that I was able to configure my validation framework it is time to actually start validating view models. I created a test that should verify that I could validate a view model, I created a test view model configured the validation framework and called the Validate method. The test failed of course as proper TDD should start with a Red test. On to make it green. So what I had to do to make it green is validate each property for the view model with each convention that was defined for the particular view model. Then when a convention indicated that this property was a match it should execute the rules for the convention, actually validating the property.

And this was _ugly_ I mean I had issues with generics versus type parameters, for each property I had to use reflection to verify if a rule should be applied and to actually execute the rule. For each property I had to check each convention, even if none of them applied. As happy and proud I was about the configuration so unhappy and embarrassed I was about the actual execution of the validation rules. And I was stuck, I had about 84% test coverage but I couldn’t refactor it to be any better.

So I sought help and I spoke with Chad about some specific problems I was having. He kept asking questions none directly related to the issues but by doing so he helped finding the root cause of my problems. He suggested another way to do the actual validation. Instead of having conventions that needed to be validated in order to get the rules for the actual validation, now the configuration will instantiate new rules specifically targeting specific properties in the view model in question. Now when a view model gets validated only the rules that apply to this specific view model will be evaluated. Nothing more nothing less and all the hard work happens only once, during configuration, not at every validation. Kudos to Chad!

But that was not the underlying issue, the real problem was that I started all wrong, instead of starting on what is important, the actual validation I started at the configuration (the cool stuff). And by doing so I was limiting the way I could do the actual validation.

The lesson Learned

Find what the real purpose is of the new functionality and start making that. Then continue with the other functionalities that are not part of the actual core. This means that for the FubuMVC.Validation framework I first had to create the actual validation functionality in the semantic model. Only after that was working the way I wanted too I could start on the DSL to configure the semantic model. The funny thing is that my DSL almost looked exactly the same the second time around, but now I could actually validate as well.

Also even do I don’t think that striving for 100% test coverage is not the most important thing to go for when you are developing, knowing where your test coverage is high and where it is low _is_ important to know when you are developing. The second time around creating the FubuMVC.Validation framework I had very good test coverage around 91% but I noticed that in an important part of the framework (the semantic model) there was an area that had significantly lower coverage than the surrounding areas. So I looked into it and found an execution path not tested at all, so I added a test that should verify what I wanted to happen. And guess what, it was failing. The one little area that I missed to test was actually failing; it was also an area that didn’t get used as much as other areas so when this would have gone wrong I would most likely have spend too much time debugging it. But now that I can see my coverage I could identify problem areas and fix issues before they even surfaced. Thinking that you have good test coverage is not the same as knowing you have good test coverage.

I hope this can be of some help to you as well, it was fun realizing this myself.

No comments yet!

Mark is reading

 
Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 Unported License.