The Psychology of Writing Bad Code — Part 1: Fears & Biases
I like to think, whether misguidedly or not, that I am a fairly good developer. However, I have written some truly nasty code in my time and I would guess that I am not alone in having done so.
Many articles have been written on the subject of what makes code bad and what we can do to write better code, but I want to go deeper. In this article, I will lay out the theory that fear and a common human bias are responsible for a lot of the occasions in which good developers knowingly write bad code.
The Fear Spiral
Fear is an emotion which shapes the way people act in their professional lives so greatly that many would be embarrassed to even speak about it, and programming is no exception to that rule. When we push bad code we can cause outages which make people angry and lose people money and it can all be traced right back to our door. It is, therefore, understandable that this taints the way we act in our jobs.
I have certainly been guilty of writing code which duplicates functionality for a new feature because I was too scared to rewrite mission-critical code which was written by a developer who was much more senior than me.
Unfortunately, when we duplicate code out of fear, we complicate the codebase, making it harder to understand. The mistake becomes permanent because the people who come after me will assume that the duplication happened for a good reason, and the resulting lack of clarity in the code then leads developers to be more scared of upsetting the way the code works. Future fixes, therefore, magnify the problem. Pretty soon we end up with a piece of functionality that nobody properly understands. That is the fear spiral.
‘The way we’ve always done things’
Every software project has an established pattern for the way things are done, whether explicit or implicit. This can span everything from the style guide to the large frameworks used in the code. It is, of course, important to maintain some sort of stylistic and technical consistency across the project, as this reduces complexity and makes the software easier to work on, and measures like consistent style guides are a good way to achieve that.
However, there is a problem. The problem is met when consistency is adhered to so strongly that a piece of software becomes frozen in time and all advances are ignored in favour of not incurring the risks of modernizing. The technological ground is constantly shifting beneath our feet, and if we don’t make some attempt to move with it, we will eventually find ourselves in deep trouble. Documentation disappears; packages become deprecated, and more adaptable competitors can leverage newer methods to their advantage.
This is a different type of fear at play. It is the innate conservatism in all of us saying that, if we can just keep everything then the same then we will all be fine. Writing code against your better judgment because “it’s the way we’ve always done it” can get people stuck in bad habits for years.
External Pressure
Every developer feels under some degree of pressure to deliver their work quickly. Clearly, the fault for this does not lie solely at the door of the developer who writes the bad code, but the fact stands that the perception of being under pressure frequently leads to developers writing code which they know will be difficult to maintain, unstable and possibly will need to be completely rewritten.
We are all hugely susceptible to external pressure, and it is all too easy to externalise the blame for doing bad work when it was done in the face of large pressure. Everyone must be able to recall a time where they needed to deliver a feature or fix as soon as possible and they ended up cutting corners as a result. You probably felt like it was fine because you were instructed to do so.
However, seemingly external pressures are often actually self-imposed. It is rare that something actually needs to be done so quickly that you can’t spare the time to do it in a stable way, and a lot of time squeezed work could be avoided by better communication earlier in the process. Frequently, it is a combination of pride (of being able to deliver the work in an unrealistic timeframe) and fear (of being perceived as lazy or slow), which drives us to accept such short time limits and those constraints are internal, not external.
The big problem with working in this way is that it causes the build-up of technical debt. We tell ourselves that, because we have managed to get this far without serious problems occurring, there is no reason that we can’t carry on going with the same corner-cutting mentality. In behavioural economics, this is referred to as the ‘hot hand fallacy’; the idea that people can somehow be ‘on a roll’ and keep defying the underlying probability of failure. Unfortunately, all results gained from drawing on technical debt are merely an illusion. The accumulation of technical debt causes adverse effects on stability and performance until it is repaid in the form on refactoring and retrospective test coverage. Failure to pay down a project’s technical debt quickly results in bug fixing taking up the majority of development time and a massive slow down in the development of new features.
Conclusion
Fear, conservatism, and the hot-hand fallacy are just some of the ways in which our psychology gets the better of us as developers, and prevents us from delivering the quality of work which we know we should be producing. But understanding that is the first step towards preventing our own bad habits.
In the next part of this series, I will explore measures that can be taken within a company, once we acknowledge these fears and biases, to prevent them from having a negative impact on the project.