I'm writing another MVC3 app. I'm in the same world of pain with respect to magic strings and anonymous classes. I don't like it here.
I'm sorry, but who on earth thought that this was a good idea for a method signature?
I mean, seriously? Six strings and a Dictionary<string, object>? And that's a sensible collection of arguments? Why not add in a RouteValueDictionary (another string/object dictionary) for good measure? Oh, never mind.
But surely there are smarter overloads than that, right? Well, yes - and honestly, you just couldn't make this stuff up:
Oh My Friendly Geranium, but who on earth thought of this - and why wasn't it knocked on the head by someone sensible? MVC team: I'm really sorry, but IMO you've completely missed the point of a strongly-typed language. I know you've taken a lot of flak for this over the past few years but, to be honest, it's kind-of deserved :(
So, what on earth do we do about it?
When we're in a world of magic-string pain, the first thing to do is generally start creating some conventions. The second thing, of course, is that we test those conventions using unit tests. Hold on a second, though: we're using a strongly-typed language and yet we're *writing unit tests *to test our conventions because we're using strings and anonymous classes? Why don't we have a tool that does this for us?
We want a convention-based test harness that:
- Runs on every build.
- Has a set of conventions that are clear and unambiguous.
- Doesn't make us manually write tests.
- Will auto-generate test cases for every new piece of code we write.
- Is refactoring-friendly.
- Is fast.
- Will fail the build if something's wrong.
I think we've forgotten something important. Can anyone point to a tool that's all of the above, comes pre-installed with every version of Visual Studio and requires zero integration work, no NuGet packages and just works?
Anyone? Anyone? No? Here's one: csc.exe. Yep, that's right: use the compiler.
Call me old-school, but a compiler is all of the above. Consider this method:
Think about it: why don't I have to test that a and b are integers? Sure, I should be testing for edge cases here, but I don't have to type-check or null-check my inputs. Why not? Because the compiler is enforcing the convention that when I say "int", I mean a 32-bit integer and it simply won't let anyone pass in anything else.
I don't have to write a single unit test to enforce these conventions. The compiler will provide me with fast and reliable feedback - at compile time - if I've broken anything, which is far better than getting the feedback at run-time using unit tests (or worse, at run-time when a user hits an issue).
I think we as developers can afford to take a bit more time to write strongly-typed code, e.g. HtmlHelpers for controller actions. Try this one:
You can make your code infer the controller name, the action name, the area and all sorts of things without ever having a magic string. You could even add strongly-typed parameters to it (built using a fluent interface) so that it's effectively impossible to get it wrong without the compiler complaining.
So why don't more people use such a great convention-based test tool? I have no idea.