Humble coding

Not long ago, I wrote a beautiful piece of code. I was very proud of how decoupled it was, how flexible and reactive. I iterated over it a few times while testing the solution in the wild and incorporating reviews from my peers. It felt perfect to have all tested ideally. Everything went well until I started seeing some unexpected behaviours. It turned out that the app wasn’t prepared to consume my feature as a reactive stream, and in some circumstances that I had previously missed, it started behaving a bit strangely. So I have two paths to choose from. On one hand, I could have continued to refine the code that utilises my beautiful reactive class, or on the other hand, I could have found an alternative, albeit less elegant, approach that does the job in a traditional, imperative way. A few years ago, I would probably stick to my guns and want to show the whole world how good my solution is and how wrong the code that breaks using it is. However, it would likely take me another week to tweak the code, not to mention conversations with other devs who maintain that code every day. Fortunately, I now understand that the code is not about me, but about the product we maintain and the team I work with. So I decided to revert to the reactive approach and go imperatively. It turned out to be a straightforward change that is also decoupled. Of course, there are some tradeoffs, but the code is relatively clean.

The more experience I gain in software development, the more I recognise the essentials in our craft. Code is not for the machine but for humans to read, so unless you work in an industry that requires performance at the top level, you should focus more on clarity rather than speed. It is more important for code to be correct rather than fast. No matter how quickly you do something, you waste all the effort if it is wrong. The same goes for the beauty of code. I tried to apply a reactive pattern to the code that was not prepared to consume streams in my example. Great idea if everybody is on board and you have a lot of time for refactoring. Since the code is intended for humans to read, applying an abstract pattern that hides complexity, but also often the intentions, could be a mistake. It is much better to take a step back and create a simple solution that works and can be easily understood, even if it falls below your ambitions.

The problem is often in taking a step back. It implies admitting to being wrong, and as humans, we are not always the best at doing that. But I firmly believe that this is the way to go if something doesn’t go as expected. Instead of looking for mistakes in the work of others, I think it is better to examine our own actions and consider how we can improve them without blaming others. Sometimes it is not a mistake in the way we implement something. It might be the way we approached it. The solution might be great, very reactive, easy to maintain, and decoupled, but it still doesn’t fit the context, and at the end of the day, it is better to remove it. No hard feelings.