I am working on inventing or finding a satisfactory validation strategy for my .Net web applications. The final model must appease the following criteria,
- I must be able to validate the entire screen in one shot.
- There must be no duplicated code.
- Objects in the system must always be 'valid'.
I must be able to validate the entire screen in one shot
This is purely a usability concern. Who wants to go through one error at a time on a page? Fix this, now fix that, opps... this one too. Oh, that would be a duplicate, you'll have to come back later. I think the system should be able to point out all problems immediately.
There must be no duplicated code
I don't want to maintain two sets (or more) of validation code. As in, validation objects on the page, and validations in the model layer. This requirement is in conflict with the other two, which makes my demands demanding.
Objects in the system must always be valid
I don't like the idea of an object being somehow malformed or incomplete. A situation where I have to check an object before I do anything seems to contradict my understanding of encapsulation. An object that starts throwing errors because it is invalid contradicts the very reason for using objects. Which is, keeping things simple. This requirement conflicts with requirement 2 because now you can't just take the validations out of the object, to ensure validity the object has to do validation.
The requirements may be asking for too much, but I feel that there is somehow a way to satisfy them all, and still have a fairly elegant solution.
Back to Performance
So, I am currently comparing validation through exceptions against the more traditional (pre OO) return codes. My first test is performance. I have read much on the Internet regarding the poor performance of exceptions so I wanted to see it for myself and get some hard numbers. The evidence indicates that Exceptions are slower (Using 1.1 of the .Net Framework). Slower by about 100%!
The tests were fairly simple. I created an class whose constructor took 2 arguments, a string and an integer. If the string was null, or empty that was a validation error. If the int wasn't between 0 and 100 that was an error. The exceptions method just threw the various 'Argument' exceptions provided by the framework and filled in a nice descriptive error message which was passed to Debug.WriteLine. The Return code method was more difficult to code and even required a trip through the debugger (Remember, I am a bit daft after all). I had to pass an error object into the class constructor so I could get the same amount of information about the validation errors. Foolishly I declared this object as a 'struct' which meant it was being copied to the stack and thrown away, with all my error information too!
My test tried to create an object with a problem that would be caught with each of the validations. This code was run in a 10,000 iteration loop, with DebugView (sysinternals.com) open to verify the output. Here are the numbers (ms) I got for 8 runs
I can't account for why the exceptions test speed slowed down. It would probably be worth looking into. The tests were extremely quick to run considering they were attempting to create 30,000 objects each. I was amazed that so many exceptions could be handled in 10 seconds. So, while the exceptions method is much quicker to code and debug, the return codes method is the clear winner when it comes to performance.