TDD next to the Big Framework
We’re trying to create a new executable process that plugs into a pretty big services framework for a telecom system. Our code and framework are in C++. We’re test driving our design. Within a few tests, we were confronted with having to inherit from a framework class. No big deal, or so we thought. Soon the dependency chains became evident. Kind of like this picture, but worse.
Unit testing OurCode is going to be a problem!
Our first thought was to use the real header files for the framework and stub out the implementation. As we saw the inclusion of one header file exposing the web of dependencies, and the preponderance of static functions, we decided that this course of attack would be a lot of trouble. We would be stubbing framework code for days or weeks. If the framework designers would have been concerned with dependency management, the framework base classes would have been interface classes in C++, classes with all pure-virtual functions. That would have been better, but not perfect, as the interfaces are quite big, and we only needed a few features of the framework.
This is a classic problem in OO software development. Our code needed to plug into the framework and also needed a few of the framework’s services. The framework has a huge interface; it wants to be all things to all processes in the telecom system. We needed two handy things from the OO/TDD toolkit: the Interface Segregation Principle and an Adaptor.
Interface Segregation suggests that the interface needed by the client code should be tailored to the client needs. But the framework is what it is, we can’t change that. But we can define our code’s perfect interface for interacting with the framework and then write an adaptor that translates calls from our lean and mean interface to the fat all-knowing all-powerful interface of the framework. If we moved our design in this direction, we can manage the dependency on the big framework like this:
With our interface in place, testing becomes quite straightforward with the introduction of some kind of test fake.
The BFw Adaptor methods are just simple delegator methods to the framework class. So, there is very little overhead to introducing the new interface and adaptor. I expect this tiny bit of code is dwarfed by the bulk of the framework.