The trouble with shims

Shims are described in Michael Feather’s book on legacy code as a stepping stone on the path to dependency inversion – they are a technique for breaking apart untestable code.

Visual Studio 2012 ships with some libraries that are able to magically intercept and manipulate calls to code that are normally untouchable – even .NET types’ members like DateTime.Now.
When it comes to shims, I agree with the opinions expressed by the author in this post explaining the libraries that were included as part of Visual Studio 2012. In summary: they are a necessary evil in some instances, and they are a means to an end, but definitely not part of the finished product.

One of my beefs with them is that this library is developed by microsoft and hence affected by them continuing or discontinuing support. Previously microsoft shipped a tool that exposed a class’s private members via some generated code that used reflection internally, allowing developers to test the gubbins of a system in a strongly-typed fashion. There were several flaws with this that I won’t go into, but my point is that a colleague started using it, only to find out that its use was deprecated in Visual Studio 2012. Reliance on magical tools that seemingly bypass the rules of a language mean that your tests are worthless the moment they are taken away (not to mention limiting your techniques to a specific language). Microsoft is allowing the developer to take short cuts rather than forcing them to rely on feedback from unit tests to show where changes should be made to code.

Another colleague recently mentioned to our team that he was using shims to fake calls to DateTime.Now in his unit tests. This is in brand new code! He chose to neglect simply passing a DateTime instance via a constructor or method argument in favour of using a new-fangled gizmo. This is an experienced senior developer I’m talking about. The reason he gave is intriguing: “The business requirement is that it uses the current date/time“. I think that this is an issue of control, or a desire to protect his code from inexperienced developers – he didn’t want someone else to pass a DateTime instance other than the current date/time because that would go against the requirements. By not listening to his unit tests and not giving up this control he missed an opportunity to turn his work into something much more generalised, something that would work with any date. This would remove the need to change perfectly valid code if the requirement ever changed, for instance: “The business requirement is that is uses the current date/time plus one week” or “The business requirement is that is uses the current date/time in (some instance) PRQ and the current date/time plus one week in (some instance) XYZ“.

Please listen to what your unit tests are trying to tell you; work with the language features you have at your disposal; and finally: use shims if necessary to get untestable code under test, but at that point refactor to passing the dependencies in to the system being tested.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s