Let’s take a look.
The Myth of The Logical Solution
One common assumption is that every problem has a logical solution. The same sentiment underlies the question: “Will AI ever replace software developers?” I often hear this expressed as: “Programming is just variables, loops and conditions”.
But you might as well say that writing is just stringing letters together. Or that composing music is just about choosing the right sequence of notes.
To illustrate, let’s look at what would seem to be a very simple problem. We have a list of numbers and want to sort them from smallest to biggest. Surely there must be a logical solution here? How would you go about it? Take 2 seconds to think.
First, you can go through all the numbers to find the biggest one, then repeat the process on the remaining ones.
But you can also go through the list from start to finish and compare adjacent entries two by two. Swap them every time you find two in the wrong order. And repeat the process till there is nothing left to sort.
A third way of sorting is to start by selecting an entry in the list. Start by sorting the numbers into two segments: the numbers that are bigger than the entry and those that are smaller. Now repeat the process on each sub-segment.
I could keep going here, as there are 21 more algorithms listed on Wikipedia, and that’s just those that have acceptable performance.
Which of those is best?
I’ve got bad news. There is no best one. It depends on how sorted we think the list might be. On how big the list is. On how much it costs to read data. And on much more. Each of these algorithms has advantages and costs. There is no best solution.
And do you know what? It gets worse.
There is a class of problems called “NP problems”, which stands for "non-polynomial”. These problems don’t have any known algorithm that can solve them in a reasonable amount of time.
The myth of the logical solution is dangerous. Logic is important, certainly, but it is far from the only factor to consider.
Instead, as software engineers, we need to find creative solutions and craft the best possible fit for a given problem. And to do so, we first need to understand the problem.
The Myth of Coding as the Only Task
Which brings me to my next question? What do you think a software engineer’s most important tool is? A computer? The code editor? A pen and paper? Is it our mouths and ears?
Coding isn’t the only task software engineers perform. It isn’t even the most important task of software development. We first need to use:
- our mouths and ears,
- then pen and paper,
- and only then our code editor. Why?
Before they start programming, developers must first understand the problem or need. That requires communicating with stakeholders to understand their needs and expectations. A software engineer must be able to ask the right questions and understand the answers. Otherwise, we risk wasting our time working on something no one wants.
And that is the reason I'm not worried about AI taking our jobs. Because the hard part of designing a feature isn't writing the code. It's gaining a deep understanding of the user's needs.
The second step is to design a solution. It’s tempting to dive in. But first, we need to map a course. We need to think about everything that could go wrong. About how the change will impact other users and other systems. About things like performance, costs, best practices, risks, maintainability, and legal constraints.
Software design is translating requirements into software architecture. This is best done with pen and paper, not a keyboard. This requires creativity and problem-solving skills.
Once we have collected the needs and designed the system, then we can begin typing source code.
But not only for the feature. We also write tests to detect failures automatically. This ensures the code is maintainable. Ideally, we start with the tests… before even coding the feature.
And once the software has been coded and tested, the product is released. But that is just the very beginning of the story. Now comes maintenance, an important part of which is hunting and squishing bugs.
And there's no such thing as a simple bug. Stupid mistakes like simple typos can take a week to find and fix. Because bug-solving often requires deep analytical thinking and problem-solving. It's about deconstructing the logic and understanding where it has gone wrong.
As you can see, software engineering is a complex and multifaceted discipline. It requires communication skills, creativity, problem-solving, attention to detail, and analytical skills. People often believe the difficulty with in software engineering is mastering the syntax of the programming language. It's not: the difficulty is abstract thinking and modelling.
Coding is just one piece of a larger puzzle. A software engineer must be able to work with users and understand their needs. They must be able to design software systems. And then write code, test it, and maintain it.
And maintenance may well be the one task we all underestimate. Why? There is a saying: "The code you wrote six months ago may just as well have been written by someone else". Allow me to explain.
The Myth of Quick (and Dirty) Fixes
Imagine… We need to make a change, and we need to make it fast. What do we do?
We have a choice. Do we take the time to think about the impact? Do we test the result? Do we spend the time to get someone else to proofread the code? Or do we rush the change and push it to production?
If I must be honest, I’ve often taken the second route. Sometimes you have to move fast. And that’s fine.
But I’ve always paid the price. In real life, cheating can cause you trouble. But, in software engineering, shortcuts always have consequences. There is always a cost to pay.
In programming, Karma is not a belief, it’s a fact of life.
Why? Allow me to explain.
If Programming is about one thing, it’s about consequences. If this, then that, remember? It is about building a complex system with intricate logical rules. And no human mind can hold the precise details of every system’s behaviour. Nor every functionality’s logic.
When we cheat and go the quick and dirty route (instead of the slow and steady one), we create... cognitive dissonance. We create mental friction. We make our code harder to understand. We create a future cost for ourselves.
That future cost has a name. We call it Technical Debt. It means we’ve cut corners but will need to spend more time in the future making things clean.
And that’s where the problem I alluded to earlier kicks in. I can’t tell you the number of times I’ve looked at a piece of code and said, ‘Who is the complete moron who wrote this?”. And then realised that it was me when I was trying to be clever or fast. And that the moron was me.
Where now ?
There is this thing called the Dunning–Kruger effect. It’s a weird cognitive bias. People overestimate their competence when it is low and underestimate it when it is high.
To phrase things differently, a little knowledge is a dangerous thing.
Conversely, when you do become competent, you start doubting your abilities. Because you’re aware of how much of the road lies ahead. You’re aware of how much you don’t know. You realise there is still so much more to learn.
And that, my friends, is the journey ahead of us.