Reflecting on building my own tools from scratch and 'inventing on principle'

by Amir Bolous6 min read17th Jul 20216 comments

37

PrinciplesRationalityPractical
Frontpage

This is a linkpost for https://amirbolous.com/posts/build

Introduction

For the past couple of months, I've built personal tools completely from scratch. I built a way to organize and record my thoughts. I built a programming language to understand Lisp. I built a tool to generate cards for family and friends. I built a web framework from scratch. I used that web framework to ship a couple of projects.

The weird thing is that, until recently, I didn't know that I could do this. I didn't even realize this was an option or move I could make. I didn't know that if I had an opinion for how things should be, I had the right to push my view of the world into reality by doing something about it. Bret Victor has an incredible talk called "Inventing on Principle" where he touches on just this.

image

Several months later of trying to do this, I can see exactly what he meant. Here's a story/reflection on this:

Tools and Products

Every now and then, a new tool or technology becomes mainstream and garners a passionate cult of followers advocating for it. For example, this happened with Roam. This happened with Notion. This has been happening with tools and technologies long before we invented them. Often, when I would try these mainstream tools, some of them stuck. However, more often than not, I was left confused and somewhat disappointed.

That's not to say that these tools or technologies are not great products. Not at all. They're clearly good products because many people use them and recommend them to others.

Dogma

I realize now that reason these products or technologies didn't stick was because of a misaligned dogma. This is the mental model I now keep in mind: any product or tool has the potential to be great if it can solve a high frequency, high intensity problem for at least one person. Sometimes, it can even be a low frequency, high intensity problem or vice versa. For example, Uber solved the problem of moving from one place to another conveniently. React helped tackle building fast, flexible, and rich websites.

However, any technology or tool also imposes an expensive cost. It carries a dogma for how things should be. A set of implicit (e.g. react component patterns) or explicit (e.g you can't call an Uber if no driver is nearby) rules that are imposed on how you use the tool/technology and think about it to get some value out of it. To go back to the React example, React carries a certain dogma for how you should build websites to take advantage of it. You can't really use it if you don't understand the pattern of "components" which is an abstraction that drives how you use the tool.

For people who have a high frequency and high intensity problem, the cost (i.e. the dogma that is "imposed" on you) feels like an absolute bargain. It can solve your pressing problem, so who cares? You'll gladly compromise.

However for others who don't necessarily have a high frequency, high intensity problem, these tools or products often don't stick. This is precisely what happened with me in the past when trying out tools or technologies that had garnered any sizable number of followers but had personally not stuck. I realize now that the problem was not with the tool itself. It was with the model I personally carried that motivated my use of the tool.

When you build your own tools, products, or technologies, this is not an issue by definition. Since you're building it yourself, the tool or technology perfectly embodies your dogma. You have a crystal clear mental model for how the tool should be used because you built it yourself! It doesn't matter whether others get it or not. It doesn't have to apply to a large group of people to capture a large market. It just has to work for you.

Building is Empowering

The best adjective I can use to describe building my own tools is empowering. Here's why:

  1. Because I was building the tool for myself, I had complete agency in how I chose to build it. I could tailor the tool exactly to my personal workflow and have it cater to my needs. If my needs change, no problem, I could change the tool! This is essentially a living embodiment of the Unix philosophy of "do one thing and do it well."

  2. For more low-level tools where I was building a tool that would let me use it to build other things with it (e.g Poseidon or Lispy), I had an intimate relationship with the software. Intimate in this context means I understood every aspect of the system. I didn't necessarily remember every aspect of the system and I often forgot how I'd designed something, but this was easily fixable. I wrote the code so I could go back and look through what I wrote. This is a particularly special feeling because the software stack has become so deep that it's become normal to compromise on our understanding of the system.

  3. Because I built the tool for myself and understood the system well, it gave me the freedom to iterate quickly. I didn't struggle setting the system or environment up. I didn't run into obscure errors that required a nuanced understanding of a system I had just started learning. And most importantly, I had a good mental model for how I should use the system. Because I built it myself! And any tool is only as useful as the mental model you have for the system itself.

  4. Because building your own tools often pushes a new layer onto the software stack, debugging was also more challenging. Bryan Cantril has a great talk on this called debugging pathological systems. The short summary is that pathological systems are hard to debug because you don't know what level of the software stack introduced the failure. Often a failure at the low levels of the system produced several different errors higher up. The cool thing was that these types of errors force you to understand the system better. Debugging didn't feel like I was struggling with a beast in the dark. It felt like learning a complex dance with a partner (this summarizes some of the more helpful tips). It was still frustrating, but I often came through on the other side with a much clearer picture of the nuances of the system.

  5. Maybe most importantly, building everything from scratch is incredibly satisfying and rewarding. Even if it's a little slower or it's a little harder to push out features because there isn't a team behind the product. Not only do the tools or technologies fit your use cases and workflows perfectly, it gives you an emotional connection to the products you use. In the same way that you appreciate an accomplishment much more once you've experienced something similar yourself. For example, after I ran a marathon last year, I gained a lot more respect for athletes, especially marathoners with really fast times because I've experienced how painful doing one is! Similarly building things for yourself gives you a sense of enjoyment and excitement that is just incomparable to when you use a product that others have built.

Closing Thoughts

As with all things, this is a process and a journey. I did not wake up overnight deciding to embrace this philosophy. And I've only just started. I've got a long way to go. There are many others who inspire me and who I learn a lot from.

So no, you don't have to build everything for yourself from scratch. And no you should not stop using every great product out there. But know that this is an option. When there are times where you wish something existed in the world. Or you're frustrated there isn't a better solution. You can and have the right to create one yourself. In fact, if you feel obliged to do so, you should do it. Stand on the shoulders of giants, steal like an artist, and build what you wish existed for yourself and others to use.

If you've got this far, I would love to hear what you think, please say hi on Twitter.

Happy building 🚀

37

6 comments, sorted by Highlighting new comments since Today at 7:30 AM
New Comment

20 years ago I always did all of this and actually use some of those tools still today.  I heartily recommend it to everyone who will listen.  There is no better way to really understand, say, web frameworks, then to build one yourself. Nowadays, I don't do this as much because I understand more things and have already built many of  the bespoke things I want/need.

I also heartily recommend throwing your tools in the trash...or at least very seriously considering it.  Once you've understood the problem space, it's very often better to use something battle-tested.  Sometimes you'll have understood the problem space thoroughly enough before you've even finished your own tool (lol at ever finishing a software project). 

On the one hand, you'll be able to use the already-existing tools better and more effectively once you've built your own. You'll be able to take advantage of all the little things that have already been built that are just boring or hard to do yourself.  

On the other hand, sometimes (but not usually) it's harder to make an existing tool to fit exactly what you want to do then it is to build a tool from scratch to do exactly what you want.

On the gripping hand, people who build their own tools often overstate just how special a snowflake they are and just how great and needs-fitting their tools are.

There's two hard things I encounter in this area:  convincing people to build their own tools, and convincing people who've built their own tools to throw away their precious creations.

Interesting perspective, I can definitely see the value in that, I actually came across a "midwit" meme with that similar theme. What's the tool you've built that you're most proud of? What's the tool you're built that you use the most often to this day?

I've observed in myself and others that the tools we build for personal usage are often of poor quality in the sense of maintainability or craftsmanship or reproducibility. They're often built in a ramshackle way.

So in one sense, these tools don't deserve any pride cast their way.

However, some of the things that I've built and used the longest fall into this category.  These tools are very needs-fitting. This engenders some sort of pride.

There's a tool I use probably a dozen times a day and has been evolving for 20 years. It's unrecognizable from it's original state. It's nothing groundbreaking and is simple compared to many of the things I do. It's a tool for building tools.

Not long after Windows XP came out 20 years ago I really got into automating my OS. Everything from "this window should always go here" to "when I press this hotkey give me the results of pinging this server".  I wanted it to be simple enough that I could whip up something to do one-off automation of little problems that I might only need to automate for a short time. The code and practices went from C (eww) to AutoIT (ick) to AHK (double ick) back to AutoIT (still icky) and nowadays to Python, but the same principles and purposes have carried through to this day.

To make it "production-ready" by addressing the "maintainability or craftsmanship or reproducibility" mentioned above, I've recently been putting a spit shine on it all, rewriting it, and making it less tailored to me and more general purpose. It's called systa and you can see it here

I'm too involved in it to objectively say if it's a tool that I should have thrown away or not. Other automation tools exist. But I think it's (or is going to be...maybe) better for some use cases than other things that are available out there.

I did this "reinvent a wheel, then throw it away and use the regular one" with a personal note editor: first I wrote Notilo, then maintaining it became too much work so I switched to cherrytree. (But if the latter wouldn't exist, I would have stayed with the former.)

This principle goes beyond software. Consider any task you have to do, physical object, or way of relating with the world, and get obsessively detailed with building it in a way that makes sense to you. Even if you ultimately throw it out for a standard approach, the relationship you'll build in this way will be much deeper.