“Listen to your software, when it’s calling for you”

Anyone with a penchant for late 80’s pop power ballads will recognise my reference here to the smash hit record “Listen to your Heart” by the abundantly talented Swedish pop duo, Roxette. A song that that steadily builds momentum, scales rarely experienced heights of melodic seduction, and fully captivates its listener — even over repeated plays — for a total of 5 minutes and 28 seconds (album version). A songwriting masterclass if, of course, you like that sort of thing (I do).

But, I’m afraid this post isn’t about Roxette, or pop power ballads.

In my many years experience building software systems, I’ve discovered a necessity to engage in a two-way conversation with code and architecture. I’ve noticed that there’s a natural tendency to think of, for example, coding as a one-way conversation, the human being communicating a set of instructions to the computer, informing it of how it should behave in any given circumstance. Whilst we do have highly functional integrated development environments (IDEs) to provide interactive feedback, we generally think of ourselves as telling the computer what to do, without explicitly acknowledging it saying anything back to us (of course, it’s a different story at runtime).

it’s quite natural to think of coding as a one-way conversation

What do I mean by a two-way conversation, then? It’s pretty simple, really. I like to make believe that a piece of code, a unit test, an architecture diagram etc. is a living, breathing entity, that’s desperately trying to communicate back to me, the rather hapless human being who mistakenly thinks he knows everything. I reason that I’m not the one in sole control here — I need to allow my seemingly inanimate counterpart to have an equal say, some control back over me. I recognise that this living and breathing entity speaks a different language to me, and that it takes time for me to learn to translate — then understand — what it’s trying to tell me. Of course, these are very frustrating circumstances for this intangible messenger, and it evokes the feeling my baby daughter must get when she has no way of explaining to me why she’s crying. But, that’s every reason to sympathise, to prioritise the need to understand.

When I look at a piece of code, a diagram, I try to open my mind to what it’s trying to tell me. Is there a message hidden in the detail that’s reaching out to me? Is that thought in my mind that “this just doesn’t feel right” the catalyst that will lead me towards a new discovery about the problem domain? Consider your thoughts and feelings elicited in the moment to be the voice of your software communicating back to you.

Why should we bother listening? What do we stand to gain? Let me digress a little into discussing something I call the problem solving trap.

I’ve come to the conclusion over the years that excellent problem solving ability can be both a software engineer’s biggest strength, and biggest weakness. Generally speaking, we consider problem solving to be a foundational, pre-requisite skill for software engineers; and it is. However, long-term issues arise when individuals and teams prioritise the mere success of having solved a challenging problem above the holistic impact of the implemented solution.

excellent problem solving ability can be both a software engineer’s biggest strength, and biggest weakness

It’s a rather peculiar thing. When we’re presented with a tricky problem, we’re vulnerable to becoming so absorbed in the need to succeed in solving it that we lose sight of whether we’re really solving it in the ‘right’ way. For a software engineer, the buzz you get from solving problems is the fuel that keeps you going, like a drug. We can easily reach a point where we seek the fruits of the psychological high instead of caring for the correctness — or even usefulness — of the solution. The harder the problem, the more likely we are to succumb to this phenomenon.

Agile teaches us to embrace fast feedback. Our product development process is alive and it’s constantly trying to tell us when things aren’t working well. We just have to make sure we dedicate time trying to make sense of what it’s telling us — that’s why we run Agile Retrospectives. We need to apply a similar lens to the software itself.

Software becomes very ‘chatty’ when we encounter complexity. Some complexity is an inescapable part of the technical debt that builds up in translating the product exploration process into a software solution, and there’s other complexity that’s the consequence of a distributed system design mandated by the need to scale. But, there are plenty of times when we do have a choice over which direction to take. My fear is that the problem solving trap, the buzz that can be derived from introducing clever, complex solutions, has the capacity to lead us in the wrong direction.

In my experience it’s the things like…

  • an overly complex diagram on the whiteboard
  • that really ‘clever' piece of code that only one person actually understands
  • a class bloated with 20 constructor parameters
  • the sad looking unit test overwhelmed with mocks
  • that broadly scoped database transaction boundary

…that create a lot of noise, and that’s when I know it’s time to start listening carefully.

We need to explore why the noise exists, not just acknowledge what it is. We can use this as the impetus for making important leaps in knowledge of the domain we’re working in, a way to challenge our assumptions. If you don’t grasp the why, then you’re just proceeding blindly, and won’t learn anything new to progress your understanding.

We need to explore why the noise exists, not just acknowledge what it is

After understanding the why, you may decide that it’s prudent to live with the technical debt in the short-term — you may assess the debt to be low interest (see my companion post on recognising the interest rate of technical debt). Even if you don’t fix something straightaway, the discovery of the why has still enhanced your knowledge. You’ve learned something important about your domain, and you can provide valuable insight in to how it can be improved.

At some point, where we’ve continually stacked incorrect solution on top of incorrect solution, we reach the point where our software causes a constant ringing in our ears — a sort of technical tinnitus. This may also manifest itself in the persistent sound of frustrated colleagues moaning about drowning in technical debt.

One classic cause of this persistent ringing in your ears is something I like to call domain drift, a phenomenon where the system underpinning a product, bears little relation to that product’s domain. Eric Evans neatly states that “your code should be a side effect of your domain model” — try to avoid it being the other way around. Domain drift is a disease can spread quickly and uncontrollably in software systems.

The longer you leave your technology solution to drift from the domain its meant to represent, the more scattered/fragmented the business logic becomes. Although it might seem counterintuitive to say, those engineers in your team familiar with the code are quite easily blinkered by their own knowledge, and are less likely to spot the extent of the drift.

Domain drift is a disease can spread quickly and uncontrollably in software systems.

New engineering hires are much better at spotting domain drift. Some telltale signs are when it becomes virtually impossible to tie down how/why the system actually works, you begin to rely on sheer coincidence for the system’s functional integrity, and it’s just really hard to get anything done. Domain drift is one of the leading reasons it often takes many months to properly onboard new engineers.

This is a considerable blocker to fast innovation, and effectively scaling an engineering team.

I’ll be the first to acknowledge that this post is rather abstract, and that it’s not giving much practical advice.

But, my aim was to encourage you to ask questions, not give you answers (I don’t have all the answers!). This is something I’ve borrowed from the technique of coaching. I became a better manager when I understood this, and I think it’s made me a better engineer/architect as well.

You’ll ultimately be the best judge of what your software has to say, so make sure you give yourself time to listen, ask plenty of questions, and seek greater understanding.

Now back to that Roxette album...

Software engineering nut. Cyclist. Musician. Dog lover