Dependency Management

In the last few years software developers have based their work more and more on third-party libraries and frameworks. This has become common practice, especially in the open-source community. Companies also benefit from using third-party software, since this practice increases delivery rate by enabling developers to save time and focus on the ‘business’ code base. We realized that we didn’t need to be constantly reinventing the wheel; that was a smart move. However, we seem to be less clever when it comes to actually applying third-party software.

The Common Mistake

Let’s say you start a new project that involves rendering some complex type of charts. Since you are a smart and experienced developer, you start looking for the framework and libraries that fit the needs of your project best. So you end up choosing some specific framework and a couple of good chart libraries. You start a new repository to version the code of your project and, then, you include all the code for framework and libraries.

If you felt something was wrong while reading the last paragraph, you don’t need to keep reading. But if you didn’t, I strongly suggest you read the entire article.

By adding the entire framework components and libraries code, you’ve succeeded in not wasting time coding your own chart libraries and a huge framework. In addition to that, you’ve succeeded in securing that the dependency interface of your project will not change. You’ve done a good job and the benefits are great  ̶ as great, in fact, as the long term damage you’ve caused in terms of code health and maintainability.

How exactly are you damaging your project?

  • Lack of third-party code evolution: not just new minor features that might end up being very useful but, most importantly, you’re losing the bug fixing.
  • Rotting code: third-party libraries and frameworks have a life cycle, which means that, eventually, there will be an end of support for them. In other words, you’re attaching your code base to third-party code that will get old and obsolete rather sooner than later.
  • Separation of goals: since the code base of your project includes a huge amount of lines that are not directly related to its purpose.
  • Worthless static analysis: the business-related number of lines of code end up being too small compared to the total number of lines, rendering the global static-code-analysis metrics unreliable.
  • Dirty code vicious-cycle catastrophe: the third party code included in the code base of your project could be eventually modified, to add new features in the best case scenario, to add bugs in the worst. It could eventually be copied into another project, repeating the cycle, and resulting in two and potentially more local versions of the same library. Even trying to avoid all this requires extra -and avoidable- maintenance resources. Now, after a few years doing any of the above, you get your catastrophe.

Someone might think of or find a way to fix each of the aforementioned problems separately and, in every case, every single solution would represent additional unnecessary -and often manual- work.


Managing Dependencies

Nowadays, almost every programming language has its own dependency-management tool, especially the most popular ones. Each of these sets of tools provides a way to automatically solve every single problem described and, in some cases, offers extra useful features. Some examples:

  • Composer for PHP.
  • Bower for JavaScript and CSS.
  • Npm for Nodejs.
  • Maven (or Gradle) for Java.
  • Pip for Python.

In any case, instead of including your project dependency code into the repository of your project, you only need to place a single file that defines two simple things: which external dependencies are required (either yours or third party’s) and which version of each one.

How exactly are you not damaging your project?

  • Lack of third-party code evolution: not any more. Dependency-management tools will find and fetch the right version for you.
  • Rotting code: only if you stop updating your dependencies.
  • Separation of goals: only if you mess with your project (use-case overloading).
  • Worthless static analysis: not an issue. Only your code will be analyzed.
  • Dirty code vicious-cycle catastrophe: forget about it.

If you read all this, you are now ready to avoid one more form of software development foolishness. Not only that, you are also able to accomplish this wonderful task simply by using a single file. A single file for a single and simple goal: making sure that the code base of your project is only related to the purpose of your project in a sustainable fashion.