Trade-offs between dependency management and change control
When you take the first step into the software world, it is almost impossible not to encounter the term DRY (Don’t Repeat Yourself). This is because we’re using functions, abstractions, etc., not to repeat ourselves in our projects. However, is this idea always valid in every situation?
For example, think about two different parts of your system. They have disparate business logic but use the same function to solve various problems in different contexts. In that manner, should we use the shared library in these different parts to prevent code duplication? If your answer is “YES,” you need to think about your answer again while reading this article.
Using the same library in these two parts increases the dependency and coupling. This is because they have different business logic, and they can evolve independently based on the needs of the business environment. Bravo! You decreased the code lines but increased the coupling and maintenance costs.
Coupling is a measure of how much two components know about and depend on one another. The higher the coupling, the stronger the dependency. Loose coupling refers to a situation where different components know as little as necessary about each other, whereas no coupling between components that they are completely unaware of each other’s existence. 
Because of coupling and dependency issues, in distributed architectures, the famous principle is WET (Write every time or Write everything twice). The critical point of WET is reducing the amount of shared code. However, it is not possible to completely prevent code reuse. Therefore, some techniques are used to manage code reuse within distributed systems.
Shared Library with Golang
Despite the shared library helping us to manage code reuse, it contains trade-offs. When we use a shared library, we need to consider dependency management and change control.
We examine two use cases to understand the trade-offs between dependency management and change control.
In the first case, you have five services using the same shared library.
Custom Shared Library with Golang
- When shared library changes occur, every service must eventually adopt the difference because the version of the library deprecates in time. In this case, we must retest and redeploy our applications with every change. We need to be sure whether there is any deprecated functionality or not. Applications can use different versions; however, when this version is deprecated, our service will not work anymore.
- Another disadvantage is when the library is changed because of the service requirement. As a result, we lost our library generality, and at the end of the day, it includes messy and irrelevant code blocks for the other services. This will not be what we want.
In the second case, we have five services and five different shared libraries.
Multiple Golang Custom Shared Libraries
These different services use different libraries. Look messy, right? As you can guess, dependency management becomes hard in that case because our services depend on more than one library compared with the previous example: the more shared libraries, the more dependency.