Using libraries in a clean way

The software we write, most of the times depend on third-party libraries. Take for example Log4Net or a device driver. The problem in many projects is that the third-library libraries are much interwoven with the production code.

Herein lies a number of problems:

  • What if you want to change the library you are using?
  • What if the structure the library uses does not meet your design?
  • How about unit-testing (think of the fact the library might use local resources like physical devices)?

Uncle Bob states in his clean architecture that within a good design, the whole application isn’t aware of these third-party libraries. Think of a plug-in like ReSharper. At Visual Studio they didn’t have to change anything in their code to support the ReSharper plugin. Only the plugin knows about the existent of the other part of the software.

How can we create such an isolation and separate our libraries from our main architecture?

Wrappers

Wrappers could be one of the places to look into. Take for example the following piece of code, which uses a logging framework which can be accessed by LoggingFramework:

public void PerformTask()
{
    LoggingFramework.LogWarning("Logging text comes here");
}

We now create a class which calls the LogWarning from the LoggingFramework and define an interface for this class:

public interface ILogging
{
   void Warning(string text);
}

public class LoggingFrameworkWrapper : ILogging
{
    public void Warning(string text)
    {
        LoggingFramework.LogWarning(text);
    }
}

This follows perfectly the SOLID design pattern, where we now replace the dependencies with an interface:

public void PerformTask(ILogging logging)
{
   logging.Warning("Logging text comes here");
}

We have now a clean separation between our library and the rest of our software. The interfaces help us to stub the drivers very easily when implementing unit tests.

But what if we want to wrap LoggingFramework.Configuration, which holds a Configuration instance? We then also have to create wrappers for this.

public interface IConfiguration
{
   bool LoadConfiguration(string path);
}

public interface ILogging
{
  IConfiguration Configuration { get; }
  void Warning(string text);
}

You can now access the configuration instance via LoggingFramework.Configuration. At the end we are creating wrapper after wrapper. In this way, the way our wrappers are connected and maintained can become very messy.

The facade pattern

A way to prevent writing wrapper after wrapper is using the facade pattern. The main purpose of the facade pattern is to hide complexity of the system that lies behind it. Therefore you define an interface, which holds all the operations you need from within your library. The class which implements this interface will now simply call the methods within your library. In this way you delegate the calls from your interface to the subsystem.

In our example shown above, this could become something like this:

public interface ILogging
{
   bool LoadConfiguration(string path);
   void Warning(string text);
}

public class LoggerFacade : ILogging
{
   public bool LoadConfiguration(string path)
   {
      LoggingFramework.LoadConfiguration(path);
   }

   public void Warning(string text)
   {
      LoggingFramework.LogWarning(text);
   }
}

In this way you’re not sticked to the design of the people who designed the library, you can simple have your own structure within the interface. In our example we directly can now call the LoadConfiguration from within the facade. This has the benefit that it is easier to read.

Unit testing

We can now easily unit test our library, by simply mocking the interfaces. When we use the interfaces within our classes, we can use any technique (for instance dependency injection) to replace the real implementation by our mocked one. In this way we can prevent usage of real hardware, when we replace the driver with our facade.

Posted in Design patterns, Unit testing by Bruno at December 12th, 2017.

Leave a Reply