Happiness, small codebases and micro libraries
Happiness comes in small doses. That’s what I learned from Dennis Leary’s stand-up in the 90’s. Coincidentally this happens to be true in software development as well - less code is often the better. In the last couple of years we’ve seen micro services gaining momentum as an architectural approach for large and complex business domains. Micro libraries are the little cousins of micro services, both conceptually and in size. They share the same foundations and are built on the same principles, but that’s where it ends.
The idea of building a system from small independent components is not that new. For example, the tooling in unix system was built on top of this principle around 40 years ago and the concept of unix pipes was first presented in 1964 by Doug McIlroy. That’s about half a century ago. Today’s micro libraries have much in common with our favourite pocket knives such as find, cat and grep.
In similar fashion a micro library does one thing and one thing only, usually very well. For example, cookie.js is a 0.9 kB utility that simplifies cookie handling and that’s all there is to it. In contrast, a framework or a larger library does a handful of things, usually with at least a few tradeoffs. It’s pretty much the same as with the tool popularized by MacGyver - swiss army knife. It often gets the job done, but you are left with the feeling that something is not right.
You would like to have a specialized tool for the job and preferably avoid the tradeoffs. This is one area where micro services and micro libraries excel – they are simple and straight to the point. Don’t get me wrong, there is room for frameworks and larger opinionated libraries. For example, in UI development frameworks help you in organizing the codebase and make your life easier. Other examples can be found from web app frameworks.
The idea of packaging functionality into libraries is nothing new in web development either. We’ve seen useful specialized libraries before, but also witnessed them get bloated when it comes to functionality and size. Yes jQuery, I am looking at you and your 72 kB minified, gzipped bundle.
An example of a modern micro library is lscache. It gives you the capability to cache data in the browser with support for expiration times and cache recycling - all in one convenient 1.1 kB file. No strings attached and it works like a charm.
Introducing boundaries to a collection of utility libraries might feel like a bad idea at first. You might ask yourself why to include ten different small libraries to your app, if all those could be delivered in one handy bundle. Why to deliberately hassle with so many dependencies? I can understand this mindset, but there is other side to this coin as well.
First, the term library anchors our thinking in a wrong way, because it refers to a collection of things. A software library doesn’t have to contain a multitude of different functionalities. Second, we developers are trained to see structures and abstractions even in places where such don’t necessarily exist. Third, perhaps in the past larger libraries were the only reasonable way to re-use code across codebases due to the need for manual plumbing.
But today there is no justified reason to package utility code into larger libraries. The code can be seamlessly distributed in small libraries, included to your app, and later packaged into one bundle for deployment. Thinking in small starts to make a whole lot of sense.
Having clear boundaries on what a single library does is beneficial in many ways. First, it is easier to develop the functionality, because you have fewer things to worry about in one codebase. This means focus, which is the key ingredient for better productivity. And we know that productivity usually leads to happier days.
Third, if the developer of the micro library decides to abandon the project you are depending on, chances are quite high that you can easily take over the library and continue developing it, because the domain is very limited. This is a way to minimize risks when you don’t lay all your eggs in a single basket.
First of all, I wanted a library that doesn’t drag the whole internet with it. Actually, I wanted zero additional calories – not a single dependency. This is especially relevant after the little npm incident couple of weeks ago. Second, I wanted the library to help me in generating test data for my end-to-end tests. This is really helpful in those cases when the data, for example ssn, is defined as unique in the underlying datastore and you are writing end-to-end browser tests. As a programmer, I immediately saw the opportunity to “make my own and save some money”.
Without a moment of hesitation, I decided to wrap these functionalities into three separate repositories and make them available for others: finnish-ssn, finnish-business-ids and finnish-bank-utils. The coding was pretty straightforward, but this wasn’t an exercise in learning any new skills. I had far more important goals in mind this time.
If there is one single thing I got from my trivial experiment, it was the feeling that I have made someone’s life easier with my code. Perhaps not immediately, but most likely in the future. These three micro libraries I open sourced were a small contribution back to the community which has given me enormously in the past years. In fact, pretty much everything I have ever coded is built on top of open source one way or another. I owe a lot.
Even though I didn’t save the money myself this time, I know someone else for sure will in the future. I didn’t make a dent in the universe, but it doesn’t matter because I know that happiness comes in small doses.