Eliminate Dependencies with the Wrapper Pattern

By January 19, 2015.NET, C#, Testing

Introduction

When writing code in C#, I often come across a dependency that is hard to work with. Usually this comes in one of two forms: Static classes that are built into the .NET framework, or external libraries that don’t provide interfaces to use. Whenever I write code that takes on a dependency like this, I use the Wrapper Pattern.

The Wrapper Pattern

The Wrapper Pattern is simply taking a class and encapsulating any methods or properties used into a custom class and interface. For example:

Some of you might find the Wrapper Pattern to be similar to the Decorator Pattern, in that we’re exposing the same method or property in another class that lets us extend a method or property’s functionality. In this case, however, we’re only wrapping the hard dependency and calling through to it. We’re not changing or extending the behavior in any way.

Another thing you’ll notice about the Wrapper Pattern is that it’s incredibly simple to implement: Create an interface, create an implementing class, and use the hard dependency in your implementing class.

Using Wrapped Code

Let’s take a look at a small code snippet that has a dependency on DateTime. Using the Wrapper Pattern, we can sever the dependency and instead use an injectable interface. Say we have the following:

As this code stands, we are locked into a dependency on DateTime, and any tests we might write against WidgetFilterer would be subject to something out of our control. But what if we had an injectable DateTime object instead?

Now we have complete control of the UtcNow property and what it returns. We didn’t have to change how we were using DateTime originally, either: Instead of directly calling the static DateTime class, we instead use our private _dateTime field. With our interface in place we can test to our heart’s content with mocks or fakes, and in real code, WidgetFilterer is simply initialized (either manually, or automatically via an Inversion of Control container) with an instance of SystemDateTime.

Usages in .NET

The common .NET libraries have a ton of methods that are either static, or don’t provide interfaces. DateTime is probably the one I end up using the most, but here are some others that I’ve wrapped:

  • HttpUtility
  • Server (as in Server.MapPath())
  • Stopwatch
  • File and Directory: I tend to wrap these together, under an IFileSystem interface, since they often work in concert and both are representative of the file system. This is another benefit to the pattern, as it allows the developer to group common methods together that might normally lead to a guessing game (e.g. is GetFiles() under the File or Directory class?).

Identifying Hidden Dependencies

One of the best features of the Wrapper Pattern, in my opinion, is that it really puts a magnifying glass to your code and exposes how dependent a class is on other things. A DateTime.Today here, a File.OpenRead() there, and suddenly your class is tightly coupled to all sorts of things that make it a nightmare to test and maintain. Rooting out all of the hard dependencies and providing a list of them in the class constructor reveals how many resources your class requires. It can lead to realizing that the class might be doing too much, and that it would function better in pieces than as a whole, or it can be used to show off how awesomely-maintainable the class already is!

A Couple Don’ts

  • When you find yourself a class that’s well-suited for wrapping, don’t get ahead of yourself and wrap every public method and property that the class has to offer. Only wrap methods and properties that your code is using, not what it might need later. The boilerplate code for wrapping a method or property is dead simple to write, and your interface/class can easily be extended as necessary. Only wrap what you need at the time, and revisit when additions are required.
  • Don’t deviate from the original behavior too much. It is okay and encouraged to shore up a weak point or two in an original method’s implementation (e.g. throws an ill-suited exception when a more appropriate exception exists). However, we’re only creating wrappers here. Don’t insert a bunch of extra functionality or alter the original behavior too much. When creating wrappers, we’re essentially promising that you can use the wrapper class and it’ll behave exactly like the regular class would. If you take things too far, then consider moving all the customizations into their own class, and leaving the wrapper class to do its one job: Wrapping.

Wrapping Things Up (Pun Intended)

The Wrapper Pattern allows developers to expose hidden dependencies in their classes. It makes these classes much easier to test, exposing seams and allowing mocks and fakes to be used, giving developers complete control. With a little boilerplate, developers can implement the Wrapper Pattern and continue using the dependencies just as before, since the method and property calls do not change. The pattern enables developers to group common functionality together under one banner (e.g. IFileSystem instead of File and Directory). Like with most patterns, it can be easy to get carried away and go overboard. Wrap as needed, and don’t deviate from the original method or property’s behavior too much.

The following two tabs change content below.