ValidationResult<T> FTW!
In a previous post I described a "ValidationResult" class we've created here at work for "lazy validation", where the "IsValid" property is a nullable boolean and is set to null if the code can't determine its value without the user's help.
Earlier this week we were working on a method that should create a row in a database table and return the identity (a Guid) of the row it just created. However, we also wanted to return a ValidationResult (true if it succeeded, false with an error message if it failed). We started out by using an "out" parameter, like this:
public ValidationResult CreateFoo(int someProperty,
string someOtherProperty,
out Guid id)
This design, however, had a few problems. Firstly, we're trying to unit test everything in this project, and our mocking framework, Moq, can't mock "out" parameters. I don't think this limitation is specific to Moq, but it was enough to make us consider a different approach. Secondly, FxCop actually complained that "out" parameters should be avoided, as per this rule.
So we needed a way to return two things: the success/failure result of the call, and the identity of the created item. Enter ValidationResult<T>!
With this new class, we have an extra bit of "payload" data that we can return along with the validation result. So now our method signature looks like this:
public ValidationResult<Guid> CreateFoo(int someProperty,
string someOtherProperty)
... and it has some code like this to return its stuff:
var vr = ValidationResult<Guid>.Success;Pretty handy! Now we can test it and we're down one FxCop warning!
vr.Data = (Guid)param.Value;
return vr;
Comments
# Bil Simser
17/04/2008 1:04 PM
Payloads for validation messages are okay, but I find them to be a little clunky. Take a look at NServiceBus. The model is to subscribe to the service you're calling and have a fault message post to your subscription rather than cluttering up your service bus with the real content.
# mabster
17/04/2008 1:10 PM
I've heard of NServiceBus but didn't know what it was for. That's an interesting idea, Bil! I'll talk it through with the guys and see if it's worth pursuing. We're all very new to unit testing, mocking etc, so throwing another new thing in the mix might drive us crazy! :)
# mabster
17/04/2008 1:18 PM
I probably should clarify that our "CreateFoo" method is very close to the metal - it's in a Repository class and not exposed to the app directly. It's used by our "service"/"provider" class.