In favor of dependency aversion

The last twenty years of software development has brought the popularity of officially sanctioned package managers for various programming languages (NPM, RubyGems, NuGet, etc...) to an all-time high. It's never been more trivial to include third-party dependencies into your software, but fewer and fewer people seem to be asking themselves if they should?

Here are a few things to think about when considering the inclusion of third-party libraries, or even things like build tools, into your project.

Trust

Is the person or organization responsible for this dependency trustworthy?

If you are searching your package manager for a library that wraps a popular Web API, was it written by the organization responsible for that service, or was it written by someone else? Who is this "someone else" and what are their motivations?

If you are including a library to facilitate sharing with a popular social network, how much do you trust that company to respect your users' privacy and not unnecessarily gather personal information in order to track and profile them across applications or websites?

If the library is open source, you can and should audit the code of the dependencies you are planning to include into your project to make sure nothing fishy is going on.

Trust also extends to whether or not they are a good steward for the library going forward. Do you think this library will continue to be maintained into the long term, or will it likely be abandoned if it isn't already? It's likely that API wrapper libraries written by the organization itself will continue to be maintained because it directly impacts their business and relationship with developers, but those offered by third-parties who needed something quickly in the moment may be tossed aside as they move along to different projects.

A notable example from my past life as an iOS developer would be the Pop library for physics-based animations developed by Facebook's iOS team. I used this library heavily throughout my failed GIF creation app for iOS, Eos. Two unfortunate things happened to that library within a year of its release:

Pop ultimately met its demise following a final release in 2018, four years following the initial availability of the library, and suffering an on-and-off development cadence following the dissolution of Facebook Creative Labs. The longer you wish your codebase to stay relevant, the more seriously you need to take this kind of thing into account.

Knowledge

Is this dependency required for the survival of your application?

If the dependency stops being maintained tomorrow or breaks with a software/SDK update:

If that dependency is so integral to your application, what is making you outsource that to an external dependency?

"To save time" is not an inherently bad answer to that question. If you or your team have the domain know-how to write your own library, but budget or schedule constraints limit your ability to do so, and you can find yourself a well maintained, trustworthy library that does the job, it may very well be worth using that library, especially if it has had years of bug fixes and improvements based on real-world usage in production. A new in-house library wouldn't have that.

Just be careful if your answer to the question is "we don't know how to do what this is doing". If your dependency stops being maintained and no other viable alternatives exist for the platform you are developing on, you will probably have to scramble and do something to get your project working again. In that scenario, you will be much happier if you and your team have some level of knowledge and understanding of what that dependency was doing and the underlying domain than if you're starting from scratch, especially if you are on a deadline or this ends up holding up a deployment.

The Dependency Iceberg

Depending on the culture of the platform you are developing on, this theoretical dependency we are evaluating throughout this article may itself have a massive tree of dependencies you aren't even thinking about. In most cases, you won't be able to trust that this level of diligence has gone into the vendor's dependency auditing process, assuming there was any in the first place.

Independant Apple developers tend to be very conscious of the libraries they include in their apps and keep dependencies to a minimum, and that is the world I came from, so I tend to apply what some may call rather conservative rules to which dependencies I welcome into projects I maintain.

In the node.js world, this system of priorities is completely inverted. Node projects have overwhelming dependency trees, and while tools exist to facilitate the auditing and vendoring of these packages to circumvent some of these issues, it's so time consuming that most will choose to simply let go and let God, and hope that nothing horrible happens to those dependencies. (This is one of many things that makes that world a complete nightmare to me.)

Remember: Dependencies aren't evil in themselves, but using them too liberally can cause unexpected problems to arise in your projects, and as developers, we should try to be conscious of these risks and bring them to the attention of the table when a new dependency is up for discussion.