bugramming

The 2 Body Problem

· ashish shekar

Today, I’m going to explore some insights and perspectives that often go unspoken in the process of building a software product – things most people don’t typically discuss openly. I hope that once you read through this blog you will get a good understanding on how to gauge the situation for your work and provide estimates according to your needs properly.

Let me feed something inside your mind before reading this post,

We can never give perfect estimates, but we can make sure that we don’t give a bad one, one which you cannot recover from.

When it comes to a software product we need to understand that it also has 2 sides to it. These 2 sides often compete with each other without even knowing and here’s how!

its not a 3 body problem so its easy, right? 😉

User Facing Problem

Let’s talk about the first side of the problem. When I say user facing problem, this is something that your product team is trying to solve. This side’s focus is mainly to solve whatever roadblocks user has, that is stopping from using your software. This way product team has only 1 problem to solve, which is making the software pleasant to use.

Tech Facing Problem

Now, this is one thing that product doesn’t care about (this is my honest take), because they just want to solve the user’s problem as quick as possible. We as developers must be aware of this very fact and to be quite frank it is really hard to assess the tech if you don’t know how the current state is.

Reading the room

Let me give you an example of a system that I had worked on:

It was a web server with a single file. I thought – “wow! what a simple service” Until I saw the total lines, it was a whopping 60_000 lines of code. One more weird thing I noticed is that, when they said that it was a single file service they were really proud of it. Whatever you need you can and will find it there. But the only thing that was stopping me – well it was 2 things:

  1. The IDE was not able to load the code for ~2mins
  2. I spent ~1 hour / day scrolling to find the code

The reality is, for the past two years, they kept piling on feature after feature into the same file, never looking back. The product team was just happy to deliver new features quickly, without considering the long-term impact.

Let’s get to the bad part!

The product team had big plans for a full revamp and, naturally, they expected it to be done in record time, given how ‘amazing’ our tech team is. But here’s the twist: they wanted me to completely overhaul all the logic to fit the new requirements… and yep, you guessed it – still in that same file! Oh, the joy!

When I analyzed the code, I saw that I had to touch almost all the functions inside this file (except some helper functions). This is bad! It means there are again 2 things which needs to be changed:

  1. The whole structure of this (awesome) service
  2. Thinking of the leadership team

Here’s how I tackled this little fiasco – no, I didn’t quit (though I considered it). Instead, I took the long road of explaining why a complete rewrite was necessary, especially for a core service.

Spoiler alert: it took forever! A solid 10% of my time was spent just convincing everyone to go for the rewrite. In the end, I refactored the whole thing into composable components (the way it should’ve been from the start) and, surprise, surprise – I missed the deadline by… 3 months!

The upside of this stunt was that we were up to speed again with delivering way before our estimates – only difference is that we were doing it by evolving our codebase with all the planned features.

Its time for some reflection – how can we have planned better in the past?

To explain how I think about software, let me tell you about the room. Imagine that you are sitting in a room and you have things lying around. These things are all components of your software system – One has turned old and is breaking down, one is rusty, one is really shiny. Also, there are some things that is not visible to us, there are tensions between what you think is the state of the product and tech. We need to see them as 2 different entities, and you have to know the state of your tech. This is so important that I will not shut up until you get it. You need to know which part of your system is fragile and which is strong, which is shiny and which is old. This will help us to do 3 things:

  • Include an additional buffer in your estimates when working on legacy or outdated components.
  • Add extra time to your estimates if you’re addressing unstable or frequently failing parts of the system.
  • Apply conservative estimates for well-maintained, stable components that are in good condition.

Estimating in a Broken System

All the estimation tips I shared in the ‘Reading the Room’ section sound great in an ideal world. The reality, however, is often a bit different. More times than not, the product team is eager to solve a problem quickly – usually one that’s happening in the part of the system that’s falling apart right before your eyes (not being dramatic at all).

It’s just one more change, right?

Keeping in mind the foresight and dedication you have to keep an ideal version of the system in your mind and you have to find a middleground here. The middleground will be – “how can you turn this old crumbling piece of code into a stable crumbling piece of code”. If you do this over and over again, you will find that most of the problems that you faced during the first iteration is not there anymore. You not only deliver your product requirement but you pave the way for making it into a better system. The gist is you kickstart the process of evolution.

It’s by leaving it in a better state than it was before.


image credits