PTOM: Bend 3rd Party Libraries to Your Will With the Adapter Pattern
No matter what you do or where you work, there will always be the 3rd party library that your manager insists you use (you know, the one whose agreement was made on the golf course), or that old legacy code that is impossible to test. Now it might be easy to just throw your hands up in desperation, but you can shield your code from this big ugly untestable tangle by hiding it so that you will never know you are using the library. The easiest way is to use the Adapter Pattern.
The definition of the adapter pattern, from c2.com is:
**Convert the interface of some class b into an interface a that some client class c understands.
Now this is definitely a very useful ability of this pattern, and can solve some problems very elegantly. One area where I used this pattern with this strict definition was to convert messages from one logging framework to another. But there is really much more potential behind this rather diminutive definition. It allows you to hide whatever you want behind your own interface and only have to slay those 3rd party or legacy code dragons in one place. Now the rest of your application go along it’s merrily way.
Here is the UML for the Adapter pattern.
I got to be honest, generic class diagrams do me almost know good. I’m just not one of those visual learners I guess. Here’s what the code structure looks like.
public class ThereBeDragonsHere{
public int AMethodINeedToCallButCannotTest(xxx)
}
public interface IHideDragons{
WhatTheIntReallyMeans CallMeInsteadOfUglyOne(xxx);
}
public class DragonHider : IHideDragons{
private ThereBeDragonsHere _dragons;
public DragonHider(Dependency dep){
_dragons = new ThereBeDragonsHere();
setupDragon(dep);
}
public WhatTheIntReallyMeans CallMeInsteadOfUglyOne(xxx){
var answer = _dragons.AMethodINeedToCallButCannotTest(xxx);
return correctTheAnswer(answer);
}
}
Now the dragons are safely hidden. What’s more, you can transform the messages passed back and forth to the 3rd party library in whatever terminology that correctly defines the conversation in terms of your application. The rest of the application is now testable, mocking out your object when you need to.
In the online open meeting last week, someone asked how do you introduce testing into a legacy codebase. In this case, the speaker said that in order to introduce TDD into an app, he needed to change about 30 classes and was unsure about the implications of the changes as well as the scope creep it put on his time estimate. This is one way to introduce TDD into a code base is one technique that can help you get there. Through continuous improvement, you will have a system that is testable and maintainable.