raphting.dev

Seeing Faces in Trees

When I joined a large software project for a supermarket, I noticed an inexplicable part in the code that was about a CarController. I was curious about how this was related to our project since I was not aware of requirements related to shopping carts. My team lead at the time told me “The main supplier of these software components worked for a German car brand before. The CarController must be copypasta from that project”.

The software supplier used a highly specific configuration for Kubernetes, accompanied by style guides and documentation. The provided software was a lot of ever copied code that was not even that good. Interestingly, a couple of years later, I encountered the exact same pattern. Another software supplier with the same strategy. Kubernetes designed so that all software components are reusable, with highly specific ways of creating secrets, databases and everything that is the glue between those components. In the end, two years of work were thrown away because what seemed to be a great collection of reusable microservices was an uncontrollable mess.

Now comes my “man on the moon” moment, which started with a failure. I led the development of what I thought was a little software project. The progress was great at the beginning. Things coming to life. If you ever worked on a greenfield project, you know the feeling of awe when code starts working and what was an idea once is now a real thing.

Then came the software architecture. And refactorings. And more refactorings. And me insisting on not worrying about software architecture, until we have everything pulled together. Unfortunately, this was not understood, resulting in more refactorings, more wasted time, nothing worked, and a lot of dissatisfaction.

To salvage this convoluted code, I sat down with a close colleague. We analyzed the code. We gradually programmed and added the missing parts. We tried to work around all the shortcomings of that architecture, which was supposed to be the grand theory of our business. Unfortunately, this grand theory was reaching for the stars. The formula that was supposed to make all the parts snap in a reusable manner, it didn’t work. After 4 weeks of achieving almost nothing, we made the hard decision to throw away all of the created software. Many months of full-time Software Development down the virtual drain. What I saw twice in large scale has hit me too.

My colleague came up with a great idea. Let’s spend a weekend away. It will be good for us, to overcome the frustration, and good for the software project. We will “just write it on a weekend”. This is what I repeated once too often when I was annoyed about the slow progress of this project. “I can write that on a weekend.”

So, two man wanting to go to the moon. And we did. We spent a long weekend in a rented apartment, somewhere far away. We had a lot of coffee, a diet my mom would not have allowed me, and long nights at the desk. Sunday evening, already three days in, we knew: The train ride back home will be enough to complete the job. And so I was right. I can write that on a weekend.

Comparing the initial development to our man on the moon weekend is not entirely fair I have to admit. We could recycle the most difficult part of the software. Just a few lines of code that are hard to get right. Now we shrunk the requirements. Instead of using an AWS managed database, we used Postgres in a Docker container. Instead of AWS Lambdas we used HTTP routing inside Go. The “enterprisey” parts that cost time sometimes, we got rid of it.

What sped us up so much was not the change in used technology. I think most Software Developers would agree that the old stack costs more time but the difference is small. What sped us up was developing exactly what’s needed, without thinking much about reusability. We developed all components so that we could use them in one way only. The way our business was designed to function.

My own explanation why this obsessive focus on working extremely close to the problem is a success factor is that humans tend to see faces in trees. Human brains really like to find patterns where are none. In Software Development, I encountered this often. One thing looks a bit like the other. There must be a pattern. Instead of risking a duplication, consolidate.

A similar realization was already formulated by Jeff Atwood in 2013, when he published the blog post The Rule of Three (With ideas from the book Facts and Fallacies of Software Engineering, which was published in 2002). One sentence stands out:

We have the delusion of reuse.

If it’s good for us, it will be good for everyone, including our own future self. And it never is. We don’t have the time for the delusion of reuse (Jeff writes that creating reusable software is three times as difficult). We are not tasked to do this. We make our own lives and the lives of our colleagues harder when we try to do it.

The solution is simple. Work along the problem as closely as you can. Focus on the business logic and the requirements. Build what’s needed, not more, and build it a little better each time.

By Raphael Sprenger