Software Engineering at Google Chapter #21 - Dependency Management
(2 of 3)
At Google they repeatedly remind their engineers of the difference
between "I got it working" vs "it is working in a long term
supportable fashion" (maintenance over time)
When Google engineers import a new dependency into a project they
are encouraged to ask themselves the following questions...
Does the project have tests and do the tests still pass after you
import the new dependency?
Who is providing the dependency (well established project vs
random repo on GitHub)?
What sort of compatibility does the project need (short, medium,
How popular is the project?
How long will we depend on this project?
How often does our project make breaking changes?
What sort of usage will the project get (wide-spread vs
Who will upgrade the dependency when the time inevitably comes?
What are the incentives to keep the project up to date?
Most problems in dependency management stop being problems when
you have full visibility into how the project's source code is
used and thus can see the impact of any change.
Example: Google's monorepo pattern allows complete visibility
(because 100% of the code is in a single repo) where as a NodeJS
project will only have the NodeJS code in the repo and not the NPM
dependencies. Without the dependencies being available one cannot
easily see and reason about what a change may affect.
A solid dependency management strategy must not assume infinite
compatibility nor can it assume a stable and unchanging dependency
There are four common dependency management strategies...
Live at Head
The Nothing changes model...
Only allows changes that will not break user code
This model prioritizes stability and compatibility over all else
From a practical perspective this method isn't sustainable,
It's where most organizations start because they can't say for
certain how long their software will be in use
The largest issue with long-term use of this model is that even
if the code works fine there will be inevitably be security bugs
that need to be fixed and those changes may break the project
There are no decisions that need to be made because there are no
versions (everything is statically linked into a single binary)
The semantic versioning or SemVer model...
Is the current de-facto standard for most software
This model uses version numbers such as 2.14.5 where 2 is the
major version, 14 is the minor version, and 5 is the patch
Changes to the major version can break API compatibility with
Minor version changes are for added functionality and patch
version change are for non-breaking patches
When using SemVer you will often see things like "requires
version >= 2.14.5"
Packaging systems (NPM, RPM, PiPi, etc) have "solvers" to
automatically determine dependency trees