This post is a part of How To Ship Maintainable Product series
Dependencies are entities our system has to rely on. Does not matter if we want or not.
If a dependency is widely used in our source code we are very exposed to any future API changes in it. The problem is not that painful if we can change the code during one refactoring session. It is worse when the changes affect distributed libraries or even other products. One of the OOP principles is abstraction. Technically speaking an interface is introduced and all modules interested in particular functionality use provided interface implementation. This way we introduce an extra layer – excellent place to maintain any API changes occurring in an external library.
Big design up front?
During programming activities we are often challenged to create interfaces and use them or stick to bare implementations. Here are two things to consider:
- Is the code a prototype or early stage program? – if so then I would skip interfaces. Use dependency directly;
- Is the code a part of stable software? – if so then use own wrappers around external libraries;
- Is the code a library or API? – then I would introduce interfaces, because our code is the dependency and it should be wrapped.
Do we need dependencies at all?
The last thing to consider is the need for a dependency at all. Usually external libraries offer more than we need. We receive additional functionalities that maybe not necessary. They may even introduce errors in future. Writing own custom code covering particular functionality may be a better idea.
What do we do when a dependency is no longer supported? Or its licence terms have changed?
Limit the number of dependencies in your system to an absolute minimum. For those, you absolutely need, create a wrapper. If you write a common library youself provide public interfaces, so other developers can mock your functionality in an easy way.