External Dependency Interfacing


A project I am currently working on requires us to reference a third party assembly.  As is quite often the case the assembly is not exposing types that are unit testing friendly.  Ideally interfaces or abstract base classes would be great, but this is seldom the case.  I've been refining a strategy to consume dependencies in a indirect manner so the hard coded types don't work their way through my code essentially having a "Medusa" effect. IE: Casting all of my types into stone and then they too cannot be replaced with test mocks.
Consider the schematic diagram below.  The blue assembly is the Medusa assembly, wanting to cast all my types into stone. But wait I have a magic mirror shield! The External Type Factory.  This is intended to control the creation of types I need to consume from the external assembly.  The other issue is being able to invoke methods in the external assembly that require the hard types(Widget, Color, and Thing) as parameters.  The External Type Factory has adaptor methods to unwrap my wrappers back to their original types in an indirect manner to stop the petrification effect.

The good:
  • Stops the external hard types from preventing unit testing.
  • Can also have life cycle management benefits - ie all calls to the assembly are managed through one area of code allowing other benefits such as life cycle management (correct instantiation and disposal) and logging.
  • Fits well with IoC containers.
  • Allows tossing the external dependency away and replacement with something else at a future date with little effort.

The bad:
  • A slight overhead of more code.
  • A slight overhead of more complexity with the indirection.
  • You still need to ensure that all developers use your factory instead of going direct and preventing unit testing.
  • All types that want to use the external assembly need to have a factory available to them to be able to get the types.
  • Not really usable in XAML code.

I might add detail to this as I continue the journey down this path.