• Home
  • Blog
  • Dependency Management: A Guide and 3 Tips to Keep You Sane

Dependency Management: A Guide and 3 Tips to Keep You Sane

Dependency Management: A Guide And 3 Tips To Keep You Sane
Dependency Management: A Guide And 3 Tips To Keep You Sane

Managing dependencies is not for the faint of heart. For a single project, you may be able to keep up with dependencies on your own. For software codebases with hundreds of modules, however, even the most seasoned developer will quickly descend into dependency hell.

Don’t worry: dependency hell has happened to the best of us! There are some things you can do to keep yourself sane and improve application security. Read on to learn more about challenges, best practices, and good strategies for dependency management, and discover our three favorite tips.

Dependency management defined

First, let’s define some of the basic terminology.

A software dependency is an external standalone library that can be as small as a single file or as big as multiple files and folders organized into packages to perform a specific task. For example, if you created a messaging app and wanted to encrypt your messages, you could use an external package created by someone else for the encryption. Your messaging app now has a dependency — the encryption package — that it needs to run properly.

There are two types of dependencies:

  • Direct dependencies are the libraries referenced directly by your application.
  • Transitive dependencies are the libraries your dependencies are calling; on a basic level, they are a dependency of a dependency.
The NPM dependency network with many direct and transitive dependencies.

From: NPM Dependency Network – Graph Commons

Dependency management is a technique for identifying, resolving, and patching dependencies, (patch management) in your application’s codebase.

A dependency manager is a software module that helps integrate external libraries or packages into your larger application stack.

The importance of dependency management

When it comes to dependency management, open source software has made things more complex. Built on the foundation of sharing and reusing code, open source software now accounts for 60-80 percent of all applications’ code base. Sometimes this reaches 90 percent, which means more dependencies to manage.

So why do you need visibility into your dependencies anyway? Outdated dependencies can impact your software application in a number of ways:

  • Security. Some libraries have known vulnerabilities. If you’re not updating these libraries, your application is exposed and you may be passing this risk on to others.
  • Performance improvements. If your dependencies are outdated, you may be missing out on the latest enhancements that significantly improve performance or add new functionality.
  • Quality assurance. To keep your application running smoothly, you need to prevent problems such as conflicting or circular dependencies as well as keep up to date on libraries that have been end-of-lifed and bug fixes.
  • License compliance. With so many dependencies, it can be hard to keep track of all your open source licenses. Many organizations don’t understand that all licenses need to be compatible with each other and that they are bound not just by the licenses of direct dependencies, but also by the licenses of every transitive dependency. By not fully understanding all your dependencies’ licenses, you put your own IP at risk.

Challenges in dependency management

Dependency management can be tricky. Perhaps the three most significant problems that you’ll face are:

Conflicting dependencies

Sometimes, more than one software package needs to use the same dependency, but each of them requires a different version of that dependency. The versions may not always be compatible, and the risk exists that when you solve the dependency for one piece of software, you’ll break the compatibility of another.

Versioning issues

Updated versions of existing software and components are intended to improve the performance of that software and fix bugs, so patching software with new versions is important. Versioning also allows development teams to keep track of changes they make to the project code. However, issues can arise when:

  • Teams lose track of the most up-to-date versions and install or continue to use out-of-date versions.
  • Differing components and dependencies work better with different versions of the same software, creating conflicts and confusion that could create vulnerabilities.
  • Malicious actors seek to generate versions that enable them to infiltrate your code base when they are adopted.

It’s therefore essential that every component and dependency gets scanned to ensure that versions used in each particular instance are secure.

Managing Dependencies Across Multiple Environments

Similar to the versioning issue, dependencies can behave differently when used in different environments and when they are put together with other components. Like cogs, they have to fit together properly, otherwise, the whole mechanism doesn’t work. Mismanaged dependencies can therefore disrupt or disable entire projects.  To avoid this, you need to do the following:

  • Identify the types of dependencies you’re using or need to use.
  • Assess where and how dependencies could affect things. 
  • Prioritize those dependencies that pose the most pressing risk to your project.
  • Update and remediate the most significant and risky dependencies.
  • Regularly review dependencies. Components change and versions are updated all the time. You need to stay on top of them constantly.

Best practices for dependency management

There’s a mind-boggling amount of pre-written code you can use, so it’s important to choose the dependencies that work best in your project and pose the least risk. To help you choose, check the following:

  • Compatibility. Does the dependency work in the platform you’re using? If not, avoid it.
  • Licensing. Are the license terms and conditions of your preferred dependency up to date and conducive to your project?
  • Maintenance and versioning. Is the dependency properly and regularly updated? If not, avoid it.
  • Breadth of use. Has the dependency been widely used elsewhere recently? If so, it’s more likely to be reliable.
  • Quality. Is the source code clean and readable? Is the documentation good, and does the dependency come with its own unit tests?
  • Ease of integration. How simple is it to get the dependency to work in your current workflow, and how quick and easy is it for developers to start using the dependency?
  • Size. The smaller the better. Providing a dependency does what you need, smaller is nimbler and is less likely to bloat and slow down your code base.
  • Community support. Is there an active community or forum focused on this dependency? If not, the software can quickly get stagnant.
  • Speed and efficiency. How responsive is your solution? Can you manage dependencies in real time?

Semantic versioning

Many projects use semantic versioning (SemVer) to keep track of changes in third-party software or packages they are using. The semantic versioning specification was originally authored by Tom Preston-Werner, inventor of Gravatar and cofounder of GitHub.

SemVer gives software or packages a unique name and/or number, thereby helping you identify whether your components and their dependencies are up to date and are using the latest, most secure patch. It follows a relatively simple and logical set of naming and numbering protocols that delineate if a change is major, minor, a patch, in pre-release or build, or is a change for development purposes.

SemVer is popular for several reasons. First, it’s quite simple to help you keep track of changes, and it indicates what kind of change happened and at what point in development. SemVer also gauges update risk based on whether a change is major, minor or patch; most importantly, it helps developers avoid dependency hell by making it easier for them to resolve version conflicts and know what versions are acceptable to use.

For these reasons, we recommend that you apply a versioning protocol such as SemVer to your dependency management practices.

Regular updates and maintenance

We’re all familiar with the practice of installing software updates to enable software to run more smoothly, ensure that it’s compatible with new platforms or new versions of existing systems, and enable it to run more advanced or refined features. The same applies to components and dependencies that are used in the software development pipeline (SDLC).

It is important to make sure that regular updates to components and dependencies address any flaws and weaknesses that have come to light. Attackers are always seeking vulnerabilities, or ways to exploit vulnerabilities, and you can be sure that if you’re using a popular component or dependency, the bad guys are working on ways to compromise it. Updates constantly counter these efforts to undermine your software, so by applying them regularly when they become available, developers and DevOps teams can ensure that they keep their dependencies secure.

This means it’s necessary to constantly scan for vulnerabilities, then identify and remediate them. It’s simply not enough to implement a round of due diligence either during the development process or at its end before you ship software. Regular maintenance is necessary to ensure that every dependency you use is secured and updated.

Automating dependency management

Implementing maintenance on an ongoing basis isn’t easy, because the volume of software and applications being developed is continually growing, which results in a rising volume of usage and an increasingly complex network of interrelationships. Manual dependency management in this environment simply can’t cope with the size of the task. For the process to be comprehensive, fast, and effective, dependency management must be automated.

Barriers to adopting a comprehensive dependency management policy

A recent study by CloudFlare showed that websites using outdated versions of JavaScript libraries almost never update them once they are installed, and this problem is not limited to JavaScript. With so much at risk, why would anyone fail to manage their dependencies?

Simple inertia is the main reason companies don’t actively update their dependencies. Your software is working fine, so it feels as if there’s little incentive to update it. With so many other priorities, dependency management often gets ignored.

Another reason outdated dependencies aren’t updated is due to a fear of breaking the build. Dependency management is hard, and applications depend on many libraries. You might have long chains of transitive dependencies or even circular dependencies. Updating one dependency may break another one further down the chain.

Strategies for managing dependencies

There are three primary approaches to dependency management:

  • Centralized management. This involves keeping all libraries, components, versions of third-party dependencies, and APIs in one central repository. The advantage of this is that you have one source of truth in one place, which can reduce the risk of dependency confusion and conflict. Having everything in one place may prove to be unwieldy, however, if your repository becomes massive. This could impede the speed of finding and analyzing dependencies.
  • Decentralized management. Alternatively, some organizations empower teams to manage their dependencies by themselves. In theory, this means that each team will only need to concern themselves with dependencies that are relevant to their projects, making the process of finding, identifying, and fixing dependencies speedier.  However, this approach also reduces the visibility and control of the dependencies that are used in multiple repositories, and is more likely to result in dependency confusion and conflict, when different teams independently use differing and conflicting versions of the same third-party libraries and dependencies.
  • Hybrid approach. The third approach is to combine centralized and decentralized dependency management. You could set up one mono-repo that keeps together shared libraries, versions of third-party dependencies, and APIs. All teams would use this to access and find common dependencies they use and their updates. Additionally, teams would each use their own repos for code specific to them, which is not necessarily shared or needed by everyone. Dependency confusion in shared code versioning is reduced while the ability to find project-specific code is accelerated.

Three tips for managing dependencies

Keeping your dependencies up to date is important, but this is far easier said than done. The really hard part of managing your dependencies is understanding which dependencies are vulnerable to security threats and which updates won’t break your code. With so many direct and transitive dependencies, this can be a challenge, but we have some tips to help you manage this process:

1. Prioritize. Some dependencies are more important than others, so it is important to be able to prioritize them, particularly when it comes to vulnerabilities. You need to understand exactly which open source vulnerabilities are being accessed by your code and which vulnerabilities aren’t so that you can update your most critical dependencies first.

2. Automate. Maintaining your dependencies can be extremely time sensitive when it comes to vulnerabilities and bug fixes. You can save time and reduce your exposure by automating dependency updates in your software projects and have your dependencies updated when new versions are released.

3. Establish policies. Establishing a clear policy up front about open source usage and dependency management helps prevent headaches later in development when it is more costly to resolve them. Your policies act as a playbook by telling your development and security teams how to handle these threats in your open source components. Without policies to give clear guidance, managing dependencies efficiently tends to be extremely hard if not close to impossible.

Dependency management heaven

Now that you understand the challenges that come with dependency management, you probably have a lot of questions. The answer you’re searching for is dependency update automation. Dependency update automation helps you stay current and requires less time than an ad-hoc approach. It also gives you a number of advanced features like sorting by dependency or patch type and can even auto-merge pull requests if tests pass.

With data breaches more common and compliance top of mind, developers are more concerned about dependency management than ever before. You can stay out of dependency Hell by creating a clear plan that prioritizes dependencies with vulnerabilities and handles updates automatically.

Developers and DevOps personnel have powerful new tools for dependency management available to them, which will help usher them to dependency Heaven.

Are you set up to optimize your dependency management?

Meet The Author

Adam Murray

Adam Murray is a content writer at Mend. He began his career in corporate communications and PR, in London and New York, before moving to Tel Aviv. He’s spent the last ten years working with tech companies like Amdocs, Gilat Satellite Systems, Allot Communications, and Sisense. He holds a Ph.D. in English Literature. When he’s not spending time with his wife and son, he’s preoccupied with his beloved football team, Tottenham Hotspur.

Subscribe to Our Blog