The art of failure
That was an excellent piece of code. The solution was concise, composable, highly cohesive, loosely coupled, and open for extension. I couldn’t stop looking at the beauty that came out of my fingertips. All the functional programming knowledge I recently read about was applied in creating this masterpiece. I was confident this would be my signature in the codebase. People in the feature would “git blame” to search for the person who produced this reusable solution and randomly send me congratulations, maybe flowers. It went smoothly through the review. With iterations of naming, cleaning, and so on, it was even better. Finally, I had enough ticks to merge them in, and suddenly it happened. During one of the conversations, somebody questioned whether this was what we wanted. Does it solve a real problem? Maybe it encourages some bad practices. The fairytale ended quickly, and I came back to reality. He was right. Although everybody was happy to ship the code I had just written, I decided to take a step back and opt for a simple solution, without adding the flexibility for future maintainers of the codebase. I do not regret it. It was the right thing to do.
Adding flexibility is not always the best approach, especially in a large stable codebase maintained by many developers, often divided into subteams that deliver features independently. Opening the door to creative thinking can lead people to use it in a way that may harm them in the future. In my case, it was about string concatenation. Specifically, I made our wrapper for strings composable, allowing them to be concatenated in any desired way while still maintaining the same type, so all the bindings remained unchanged. This clever idea would be good if we wanted people to concatenate the strings freely. That could be safe, but I can easily imagine a situation when it could cause a problem, and we wouldn’t realise it until somebody reported it in production. When you code for multiple spoken languages, you need to pay special attention to the word order. The tool would be convenient for someone in a rush who wants to quickly ship a solution without bothering with proper translation, composing it out of existing words, which could have been a production disaster.
I’ve learned a few lessons from this experience.
First of all, I’m not that clever. I read a lot and try new things, and I’m not afraid to use them, but it takes a lot of practice to make the proper habits and recognise the right moment to use the knowledge.
Even if you know something extraordinary, it doesn’t mean you should use it. In my case, I started to understand the functional programming approach, and I look for opportunities to make my code Haskell-like. Sometimes I do it consciously. Sometimes it just slips out of my mind. The code is not to impress someone. It is to do the job, be easy to maintain and hard to abuse. It is not about showing how smart I am but about helping the project succeed.
It is okay to fail and to be wrong. However, if you work in an environment where it is not, you are either a rocket scientist or should change your job. On the other hand, if you are always right, you are not trying anything new. The trick is not to hold to the wrong ideas, admit the failure and move on with the lesson learned.
Listening is the key. People give different types of feedback. Sometimes they say something to your face, sometimes they whisper behind your back, and sometimes they give subtle signals that you need to pay attention to. Just don’t assume they are just saying nonsense. Instead, listen and try to find something valuable in the criticism.