Willed and forced design
Roy Osherove, as a TypeMock employee, presents quite a dilemma from opinionated TDD blog posts simply because whether he has one or not, there’s always the question of agenda. Which is quite unfortunate, everyone has some sort of selfish agenda at some level. One of those posts came up in a commentary on willed and forced design, with respect to the usage of mocking frameworks:
#1 Willed Design
By writing tests, you can observe the usability of your design from a consumer perspective, and can decide whether or not you like it, and change it accordingly
#2 Forced Design
By using a subset of the available isolation frameworks(rhino, moq, nmock) or specific techniques *manual mocks and stubs) you discover cases that are not technically “mockable” or “fakeable” and use that as a sign for design change.
After about 2 seconds of playing around with dynamic languages such as Ruby and JavaScript, the idea that TypeMock is some how “impure” seemed rather silly. Yes, it bends the CLR in crazy ways, but in and of itself, I believe it has its place.
However, I highly disagree with Roy that #2 is bad, that a tool shouldn’t force my hand in a design. But there’s a bit of a straw man here – it’s not the tool forcing my design, it’s the test telling me where I need to change my design. Quite simply, if I run up against something hard to test, my first choice is to isolate that piece. Here’s an example:
public ActionResult Index() { var user = Session["CurrentUser"]; return View(user); }
This piece is awkward to test, even though HttpSessionBase or whatever is a class with virtual methods, and it makes the test ugly. Yes, I could mock the crap out of this heavyweight object, but that’s not really helping me out, is it? Instead, I’ll isolate the ugly:
private readonly IUserSession _userSession; public HomeController(IUserSession userSession) { _userSession = userSession; } public ActionResult Index() { var user = _userSession.GetUser(); return View(user); }
Instead of using a dictionary directly, I’ll hide that business behind a facade service, keeping the dictionary ugliness and duplication in one highly cohesive class. But it was the _test_ that led me to do this, because I’m tuned in to pieces that are hard to mock. File I/O? Facade. Web service proxies? Facade. Registry, HttpContext, etc. etc? All facade. I want to isolate my core application from the untestable pieces, not because they’re necessary untestable, but because I don’t want to couple my application directly to these external services. Putting these behind targeted facades eliminates all that duplication that directly using these APIs tends to encourage.
There are plenty of APIs that slapping a simple facade over tends to make things worse, not better, such as:
- Workflow Foundation
- SharePoint
And any other framework that requires you to tiiiiightly integrate with in order to be successful. So where does that leave me and TypeMock? Well, I don’t use any of those frameworks that require tight coupling, and I don’t have any pain with my current tool of choice in .NET (Rhino Mocks), so why switch exactly? For those rare occasions I might need TypeMock (DateTime.Now), I already have a solution I quite like. Yes, TypeMock could be free, but the only compelling reason I’d switch would be to another free tool with a better, clearer to write, read and scan API.