Sunday 24 May 2020

Twelve Factor App - Dependencies


The concept of the Twelve Factor app was developed by engineers at Heroku to describe the core principles and qualities that they believe are key to the adoption of the Software as a Service (SaaS) methodology.

First published in 2011 the Heroku platform is unashamedly opinionated in the enforcement of these principles, the relevance of them to effective software development has only intensified as the adoption of cloud computing has increased the number of us deploying and managing server side software.

The second principle relates to the declaration and management of dependencies:

"All dependencies should be declared, with no implicit reliance on system tools or libraries." 

Code Dependencies

Virtually all software has dependencies, this will range from your particular language and technology platform of choice to the libraries you consume for functionality that is not practical or not expedient for you to write yourselves.

For this reason most programming environments provide some sort of dependency management tooling. .NET as NuGet, Ruby as Gems and Swift as CocoaPods to name a few. Some of these tools provide the option to install packages locally for use within the codebase or more widely as system packages.

The declaration and installation of dependencies should always be explicit and clearly identified, there should never be an implicit reliance on the system to provide a dependency that could cause a runtime issue if for whatever reason it is found to be missing.

Aside from the clear declaration of any dependency, its use within the codebase should be as equally well signposted and clear for developers to see. This can be achieved by following normal good coding practices such as ensuring class dependencies are declared in constructors and using dependency injection to avoid a class creating its own dependencies internally.

System Dependencies

It can be challenging to completely avoid having a reliance on the underlying system on which your software will run. As with the code dependencies we've previously discussed it is important that these dependencies are clearly stated and managed. It should not be the case that the existence of a system dependency is assumed. A common scenario for this issue to make itself apparent is if the software in question invokes the shell to run commands, for example running Curl commands or manipulating the file system.

These kinds of dependencies should either be fulfilled by using the appropriate areas of your technology stack, by vendoring the necessary packages into your application or by using technologies such as Docker to ensure that the necessary dependencies are installed on the system as part of the deployment of your software.

The more your software has a dependency on the system it is running on the less portable it becomes and the more challenges you will have if you need to change or adapt your deployment strategy.

Self Explanatory Application

The aim of this principle is to ensure your software is self explanatory. By this we mean that a developer can gain all the knowledge they need to run and work on your application simply by looking at its repository.

An application that is self explanatory is also agile in nature. This agility manifests itself both in the effectiveness of the teams working on the software and in the options that become available for hosting and deployment.

Dependencies are virtually impossible to avoid, but all developers will have war stories of a vexing issue they've had to deal with that has boiled down to an unclear or complicated interaction with a dependency. 

No strategy is likely to avoid these kinds of issues permanently but recognising that dependencies are a potential source of pain and doing all we can to mitigate them is a sensible approach to take.


No comments:

Post a Comment