Writing code badly
As every developer knows, it seems a lot easier to write bad code than to engineer good code. We can define good code as being easy to understand and safe to change. Bad code is therefore the opposite of this, where it is very difficult to read the code and understand what problem it is supposed to be solving. We fear changing bad code – we know that we are likely to break something.
My own troubles with bad code go all the way back to my first program of note. This was a program written for a school competition, which aimed to assist realtors to help their customers find the perfect house. Written on the 8-bit Research Machines 380Z computer at school, this was 1981’s answer to Rightmove.
In those pre-web days, it existed as a simple desktop application with a green-screen text-based user interface. It did not have to handle millions, never mind billions, of users. Nor did it have to handle millions of houses. It didn’t even have a nice user interface.
As a piece of code, it was a couple of thousand lines of Microsoft Disk BASIC 9 code. There was no code structure to speak of, just thousands of lines resplendent with uneven line numbers and festooned with global variables. To add an even greater element of challenge, BASIC limited every variable to a two-letter name. This made every name in the code utterly incomprehensible. The source code was intentionally written to have as few spaces in it as possible in order to save memory. When you only had 32KB of RAM to fit all of the program code, the data, and the operating system in, every byte mattered.
The program only offered its user basic features. The user interface was of its time, using only text-based forms. It predated graphical operating systems by a decade. The program also had to implement its own data storage system, using files on 5.25-inch floppy disks. Again, affordable database components were of the future. The main feature of the program in question was that users could search for houses within certain price ranges and feature sets. They could filter by terms such as the number of bedrooms or price range.
However, the code itself really was a mess. See for yourself – here is a photograph of the original listing:
Figure 1.1 – The estate agent code listing
This horror is the original paper listing of one of the development versions. It is, as you can see, completely unreadable. It’s not just you. Nobody would be able to read it easily. I can’t and I wrote it. I would go as far as to say it is a mess, my mess, crafted by me, one keystroke at a time.
This kind of code is a nightmare to work with. It fails our definition of good code. It is not at all easy to read that listing and understand what the code is supposed to be doing. It is not safe to change that code. If we attempted to, we would find that we could never be certain about whether we have broken some feature or not. We would also have to manually retest the entire application. This would be time-consuming.
Speaking of testing, I never thoroughly tested that code. It was all manually tested without even following a formal test plan. At best, I would have run a handful of happy path manual tests. These were the kind of tests that would confirm that you could add or delete a house, and that some representative searches worked, but that was all. There was no way I ever tested every path through that code. I just guessed that it would work.
If the data handling had failed, I would not have known what had happened. I never tried it. Did every possible search combination work? Who knew? I certainly had no idea. I had even less patience to go through all that tedious manual testing. It worked, enough to win an award of sorts, but it was still bad code.
Understanding why bad code is written
In my case, it was simply down to a lack of knowledge. I did not know how to write good code. But there are also other reasons unrelated to skill. Nobody ever sets out to write bad code intentionally. Developers do the best job they can with the tools available and to the best of their ability at that time.
Even with the right skills, several common issues can result in bad code:
- A lack of time to refine the code due to project deadlines
- Working with legacy code whose structure prevents new code from being added cleanly
- Adding a short-term fix for an urgent production fault and then never reworking it
- Unfamiliarity with the subject area of the code
- Unfamiliarity with the local idioms and development styles
- Inappropriately using idioms from a different programming language
Now that we’ve seen an example of code that is difficult to work with, and understood how it came about, let’s turn to the obvious next question: how can we recognize bad code?