The programming of my favorite color

The other day my daughter asked me what my favorite color was. I answered right away without thinking: “blue”. It wasn’t the first time I’d been asked, and it’s something I’ve been sure of since I was a kid. Or not.

This time, I’m not quite sure why, after answering my daughter something in my head started to twist: “is blue my favorite color?”. Suddenly I found myself questioning something that had been burned into my brain for so long that I can’t remember when I decided blue was my favorite color.

If I stop and think it through, in my case this answer has been completely programmed since childhood and lasted until a few days ago as an absolute, unquestionable truth. But if I analyze it, every time I have to make a decision that involves picking a color, blue is never my choice. I’m sure that at some point in my childhood blue was my favorite color and that fact made itself at home in my brain, settling in so comfortably that I never questioned whether it still held until now.

Some of you might be wondering right now: “and what the hell does this have to do with software development?”

Personally, I think it has a lot to do with it, because it’s something I run into constantly when working with development teams. Every so often I face “programming” of this kind which, instead of being about a favorite color or football team, is about using a technology, applying a pattern, or preferring one practice over another.

Principles over practices

It’s common that, after a development team makes a decision, the reasons that led to it are forgotten. What’s more, it’s common for that decision to become an immovable, unquestionable truth, to the point that even if the reasons behind it change, it doesn’t matter, nobody considers whether the decision should be revisited.

It’s important to always be able to go back to the principles behind the decision to apply a practice. When the debate revolves around the practice and forgets the principle, we’re lost. It’s like debating a solution without remembering the problem. When this happens, we usually end up in a debate that completely loses focus, and we fall into a spiral where what we discuss is how to solve the new problem created by the proposed solution, instead of thinking whether we could find an alternative solution to the original problem without setting off a chain reaction of problems.

Pin down the problem

When it’s time to face a problem, it works really well to spend a few minutes writing down exactly what problem we want to solve. Once that’s done, my recommendation is to spend a few more minutes thinking about whether that’s really the problem to solve or whether we’re actually being conditioned by a problem created by the current solution. Once we’ve escaped the spiral of problems created by solutions, we’ll truly be in a position to discuss the problem.

Sometimes we’ll have to adopt solutions to big problems that create small problems, and we’ll be forced to work on top of those foundations, but the most important thing is never to forget the principles, or we’ll lose the ability to question those solutions, because the answer will always be: “I don’t know, it was decided that way and that’s how we’ve done it ever since. Better not touch it just in case”.

Not just at the code level

We constantly run into this kind of problem in other areas of software development. It’s common to end up with convoluted deployment processes, where we ease the pain by complicating the process with solutions that in the long run create more sources of pain and drag us into the spiral I’ve already talked about. This is common when it’s time to set up automated deployments of complex systems, or when developing the business processes themselves.

Careful with the diagnosis

Another common problem is criticizing the principle after a traumatic experience applying the practice. Another is just the opposite: stigmatizing the practice when the mistake was trying to apply it to a problem it wasn’t suited for. Some examples could be:

  • Getting a continuous integration environment wrong and concluding that continuous integration doesn’t work.
  • Inverting the test pyramid and reaching a point where tests are very fragile and expensive to maintain, but concluding that automated tests aren’t worth it.
  • Deciding to use a non-relational database to solve a problem better suited to a relational one, and ruling out non-relational databases for anything.

Let’s not forget to deliver software

The reality of every project is that there’s always something that could be done better. There’s always a process that could be optimized, tests could be more complete and readable, code could be refactored or a different approach could be tried. But there’s no need to go crazy; let’s not forget that we develop software for a purpose and, if we don’t deliver it, users won’t be able to use it. Developing software and not delivering it is the same as not developing software.