No 3rd Party Dependencies!

Published on: Sun Aug 11 2024

Introduction

A common line that I see in many open source software projects is “No third party dependencies!“. To me this seems like a very odd tagline. So in this post I would like to discuss the popularity of no-third-party-depedency-software, the movement behind it and my take on the whole thing.

The Evidence

Here are some recent examples, that I came across in my web development endenvors:

For more examples, feel free to browse this GitHub repository search: https://github.com/search?q=zero%20dependency&type=repositories

I even came across a “Zero Dependency Club”: https://github.com/nalgeon/zero

Another point of evidence is the recent rise of popularity of non-traditional javascript frameworks such as HTMX and the AHA Stack, trying to purge a lot of “bloated” technologies such as React and SPAs in general. This movement embraces the KISS principle and takes a stance against single page applications and instead opting for a MPA (Multi-Page-Application). This helps to simplify the overall infrastructure (but not necessarily the business logic or overall code).

dependency - noun

To talk about this whole topic in depth, we need to define what we actually mean by “dependency”. Obviously, if we’re being pedantic, everything you are using could be considered a dependency. So there can never truly be no-third-party-dependencies software.

What we are going to refer to as “dependencies” are libraries and frameworks in a programming language, that go beyond the building blocks (e.g. the syntax, runtime or compiler) and the standard library. Also the tools ad build system around the software (e.g. Git, Bash, Make, …) do not count towards a dependency. So a Software using Make can still be considered dependency free.

Why fewer dependencies?

Disclaimer: Every point here is highly depdenable on context. They are not general statements. You will have to evaluate the points I am making for your own case.

To answer this question, you can go down a lot of different rabbit holes. Let’s dive into some of them:

Package Manager Incidents

Behind all software are people. Maintainers, contributors, users and so on. And people are unpredictable. A lot of popular and sometimes critical software is often maintained by one person. And if that person decides to stop working on the software, change the license, pushes a buggy update or takes it down completely, there can be catastrophic consequences for whole economies. Below you can find two examples of these horror scenarios:

So in short, people are always involved in software and people are not perfect. So if you want to reduce the chance of this happening to your codebase, reducing the overall number of dependencies is a sure way to do it.

Bundle-size

A couple memes to get this section started. If you do not understand it, I envy you - keep it that way.

node_modules meme 2 node_modules meme 3

node_modules meme 1

If you are using external code, chances are, you are not using all of it. So with every dependency you are importing some dead code, that will never be used in your code. Yes, there are techniques to make this better (f.e. bundling optimizations and tree shaking), but those are not perfect and sometimes rely on the library itself supporting the techniques (e.g. tree shaking).

Learning

Implementing something on your own is one of the best ways to learn about it. Always looking for the next best library if you hit a roadblock in your project is lazy and not forward-thinking. If the utility is small enough, you can even copy-paste the code from the repo in your codebase directly and play around with the code, so that you understand the implementation (don’t forget to check the license and comment the source though!).

So if you are doing web development, write your own little frontend framework. Implement some reactivity and components. You can always opt for the big framework, but having a deeper understanding of the tools that you are using will surely improve your code and productivity.

This might not be relevant for your highly critical SaaS application, but if you are working on something purely for the fun of it, try getting your hands dirty more often. It will be very rewarding in the long run.

Managing Complexity

There are two kinds of complexity: necessary and accidental. Some things require a certain overhead or complexity in their implementation. But a lot of things are over-engineered from the start and amount to a lot of accidental complexity that does not have to be there inherently.

My favorite example for this are databases. Yes, there are many types of databases: Key-Value-Stores, Relational, Non-Relational, Graph, Distributed, and many more. A developer might use redis, MySQL, and even MongoDB in their project for different use cases. Even though they could use MySQL with a custom KV Table and a JSON column to replace redis and MongoDB. Obiviously, if you are scaling your application immensly, it will eventually make sense to use dedicated solutions such as redis, but the vast majority of projects will never reach that point and making these technologies too early will cause more harm than utility.

I should mention, that writing your implementation of something does not guarantee the absence of accidental complexity. It very much depends on the use case and your resources. So take this point with a grain of salt.

Why more dependencies?

Disclaimer Reminder: Every point here is highly depdenable on context. They are not general statements. You will have to evaluate the points I am making for your own case.

Complexity

I will keep this point short, because it is even more context-sensitive than the other points.

Even though some libraries might cause accidental complexity, the fact that you can mentally offload that functionality and responsibility (such as testing & updating in the future) to another repository, might be worth the outsourcing.

Security

There is a common saying the web-development world: “Do not implement your own auth”. Wether this is good advice or not*1, the reasoning behind it, is that there are a lot of things to keep in mind when writing code about a highly critical part of any application*2.

The general point to make here, is that some utilities require a lot of knowledge and consideration. So doing the testing, updating and edge-case discovery yourself could lead to a lot of vulnerabilities being exposed in your application.

In these cases, it can be wise to choose an external library, instead of rolling it your own.

*1 I would argue it is good advice, although you should implement your own auth to better understand the moving parts

*2 Password hashing, XSS, Session Management, Input Validation, 2FA, OAuth, SSO, …

Community

As mentioned earlier, there are always people behind software (don’t you dare talk about autonomous AI coding agents). When you are deciding on what library to use, projects with a lot of maintainers, contributors. This is usually a green flag to me, since it lowers the chances of the project becoming unmaintained soon. We will talk more about this point later in the post.

Tips on selecting dependencies

If you are going to drink, at least drink responsibly. Ehh sorry wrong post. What I meant to say (write?): If you are going to use external code, choose wisely.

Look for recent activity

Depending on what utility you are looking for, it is a big green flag, if you can find activity on that repository. Some software is small enough to be considered “done” and not ever have to change. I would argue that is the exception though. Especially if you are working in an environment such as web development, which is rapidly changing every year. A quick look at the latest release or latest commit.

Personally, to consider a repository, I make sure it has had some activity in the last 6-8 months.

Look at the license

Some open source software looks like you can just install and use it right away. But just because the source code is available, does not mean it is freely available for all use.

Here are two examples of software that you are not allowed to use commercially without obtaining a license (for $):

Look at the maintainer

For smaller projects, it is always a good idea to visit the GitHub, Twitter, LinkedIn or YouTube profile of the maintainer. Finding a rich digital presence is a green flag to me and can give you some confidence that that person is passionate about software.

Look for credits to other projects

A green flag for any open source project is linking and citing similar projects in their README. This also gives you the opportunity of exploring the space of the particular problem you are trying to solve for with that library.

Look for standards APIs

Sometimes, a dependency can turn into a burden in the future. For example if the project gets discontinued or you want to switch to another library for whatever reason. In those cases, you are going to have to do a lot of refactoring in the codebase.

Here are two examples, how this can be mitigated:

In Conclusion

In conclusion, there is no definitive conclusion. As always in any field tangential to engineering, there are no silver bullets. There are many variables to consider in every scenario: scale, resilience, long-term support, you & your team, deadlines, …

Anyways, code responsibly. peace out.

Sources