Part I: A Journey of a Thousand Binaries – Types of Software Dependencies

Everything you need to know about software dependencies, a key part of our software, and how important they are during the whole software development process

A Journey of a Thousand Binaries

TL;DR

We use software dependencies as part of our ongoing daily work. In part one of this series, we’ll take a look into what dependencies are, why we use them and the tools we can use to manage them and gain trust in our software supply chain.

Software Dependencies

Dependencies are artifacts that enable applications to be displayed, execute, or deliver functionality to several types of consumers – from end-users to third party developers or applications. End-user applications most often than not require “resources” to provide the full experience or behavior intended for their users. Resources like icons, images, pdf, text and rich text files, graphical content are as important as libraries and frameworks! Applications depend on a specific version to work as expected!

For example, an SPA (single page application) will most times be written using a framework as a foundation, adding libraries to incorporate widgets/components from other sites, define a collection of style sheets to display cool interfaces or themes, and support i18n. All these artifacts: images, icons, music, css files, text translations, libraries, modules, frameworks are dependencies (binary and non binary) and they will be used in different stages of the development cycle.

There are few applications that do not depend on external or internal artifacts, but for the rest of applications and systems out there, we need to think about dependencies. Dependency management (or the lack of it) is not a concern exclusively for developers, all stakeholders involved in the software development cycle will be impacted by performance, security, licensing, and compatibility issues.

BinariesBinaries (aka software packages, artifacts, containers, images…) have become the center of gravity for the modern software supply chain.

File Formats : Binary and Text

All files in your computer are encoded into binary or text. While all files regardless of their format contain data stored as a sequence of bits (binary values of 1s and 0s), in text files the bits represent characters, while the bits in binary files represent custom data. For example if you were to use a simple text editor to open a Word document, while some of the content could be recognized, you would also find information that is not legible to you.

Dependencies can be in binary format files like zip, jar, rpm, nuGet or textual format like css files, or plain text files. For the sake of simplicity I will use binary dependencies or non binary dependencies in further references.

Why do we use dependencies?

There are several reasons why we add internal or external dependencies to our applications, the most compelling ones are:

  1. Speed up development
  2. Increase functionality
  3. Fulfill organization’s requirements and specifications

1. Speeding up development by reusing code

Many applications have to deal with common tasks such as interfacing with I/O devices, large storage units, network resources, and user interfaces. In this common scenario we would like to reuse components that deal with said tasks in a secure, performant or fulfilling special considerations. There is little to be gain if we invest resources in creating libraries, components, modules, or frameworks that provide most of the time a superset of the functionality that we seek from scratch. In the worst case scenario we might not consider all possible use cases or test profusely the functionality that we require.

We stand on the shoulders of giants and leverage all the hard work and lessons learned from the software developers of our past.

2. Increase functionality by adding specialized libraries or modules

I remember some years ago when a particular part of an application under development needed a simplified state machine. The answer of several of our junior developers was: yes! we can write one quickly… Some of the senior developers were a little cautious because we knew that there already exist very well tested, abstract and fully functional libraries for that use case. Instead of suffering from a severe case of “not developed here” syndrome we understood that by using well written, tested, documented, secure and performant libraries we would be reducing concerns instead of acquiring more.

3. Fulfill organization’s requirements and specifications.

Depending on our organization or consumers we may need to meet strictly defined security, licensing and minimal offered functional requirements, one of the most typical ways to fulfill those requirements is by adding ad-hoc modules.

Examples of special requirements are custom http headers and or cookies, security authentication protocols and logging formats.

A closer look at dependencies

Dependencies are the internal parts of our software and they can be used at different stages of the development lifecycle: development, runtime execution and testing. Dependencies are not all the same!

Software dependencies can be …

  • Collections of binary files containing high-quality tested code that provides functionality that requires significant expertise to develop.
  • One-line npm modules. Dependency managers like NPM have made it possible that trivial functionality can be packaged and published as consumable binary files.

Types of software dependencies

There’s no limit in the size of the dependencies. A dependency can be thousands of lines of code, like a full fledged framework, or it can be a one liner. There is a whole range of different types of software dependencies.

Types of dependenciesTypes of Dependencies: Frameworks, libraries packages, modules and resources.

Resources – Collections of files, for example templates, media (audio, video or images), plain text files or blobs that need to be included by applications to execute correctly.

Modules – Set of methods and functions that provide a self contained functionality. A module usually has an interface that specifies both the functionality it provides as well as the functionality it depends on.

Package – A collection of modules that hold in general the same functional purpose. Usually a directory that contains a file that describes metadata about the package.

Library – A collection of related functionality defined in several packages, is essentially a set of functions that you can call, each call does some work and returns control to the client or application that executed the function.

Frameworks – A framework embodies some abstract design, with more behavior built in. In order to use it you need to insert your behavior into various places in the framework. The framework’s code then calls your code at these points.

Level of dependency

Now that we have identified the dependency types, we have a clearer picture. The next step is to identify what dependencies are crucial, important, cosmetic, easily exchanged or superfluous to our own projects.

These two pieces of information help us decide the cadence of update, migration costs or cleanup efforts of each dependency and prioritize our resources!

What’s coming next

In part two of this blog post series we’ll learn more about the most famous disasters of dependencies; discuss the hidden “costs” of adding ANY dependency; how we can  “objectively judge“ a dependency.

What you can do TODAY

Meanwhile if you are keen to improve the security and quality of your software you can scan your binaries and open source dependencies using Frogbot. This tool automatically protects your git projects from security vulnerabilities, even before a release is made. If you want to have all this information alongside your development environment, there are free plugins/extensions available for several IDEs (VS Code, IntelliJ IDEA, Visual Studio, etc). Are you building Docker images? Scan your containers to keep vulnerabilities out of your pipeline with our Docker Desktop extension.

If you want to discover more about the previously suggested tools, the JFrog Platform, software dependencies and DevOps, then I’d encourage you to join our next workshop.

Happy coding!