How to write bad code

A bite of my history

If you came for the essence only, you can skip the boring part and jump to the second section straight away.

I started programming from early two liners in Basic on Atari computer my friend living on the same floor in 11 storey building had at home. I didn’t have the computer myself, but I’ve been gifted a book that taught computers starting from the basics of a transistor operation, Boolean logic, and simple digital circuits, ending with a basic Basic course at the end.

Most people aren’t so lucky today. Computers progressed massively, younger generations don’t even know what the Basic is. Today people start their digital journeys with smartphones, not square command prompt in the top left corner of the screen. Programming requires patience, at this is the last blessing a smartphone has to offer these days, bombarding us with notifications instead.

The next step on my learning journey was typing source code from computer magazines into an editor — an exercise letting me soak the syntax up like a sponge. Today you take copy&paste and you can play with the code. The clipboard appeared on my computer about seven years after I started retyping the code. The next step was always an attempt to compile and run, which usually failed as I had to fix typos I’ve made. That was an initial lesson about what compiler errors mean.

For many years, till I started my secondary school, I practised Pascal (including Delphi at the end) and later a bit of Visual Basic. I started learning C along with UNIX systems, fixing bugs that annoyed me in open source code, all with help from school friends.

But I haven’t been linking my career with full-time programming at that time. I was utterly fascinated with systems administration at that time. Thing is, there were plenty more people better than me at that. It took me some time to understand this and figure what I can truly be good at — embedded programming. From an early age and youngster I had a keen interest in electronics, I was never fully committed to it, but because how I started learning computers stuck with me and shaped me for the rest of my life — I pretty well understand digital electronics.

My C++ journey started with my first professional programmer role. I got the job soon after I finished the first year of my studies. I didn’t know C++, but I was assigned to a C++ project. I was learning C++ by reading Bruce Eckel’s book on the bus commuting to the office and back, training what I’ve learned from the book on the job. Luckily, I had a few colleagues pretty good at C++.

Newbie unknowns

Why that short history lesson? The tricky part is that till then I didn’t know what crappy code meant. I wrote some software not thinking much about the structure, when it worked it worked. Myself, I never had to return to the code I’ve written. I lived in incognizance. The reality check was… enlightening. The second lesson I received dealing with a large commercial codebase was that in the end, my own source code wasn’t the worst. That’s how I started learning how to write bad code. Before that, I had to learn how to deal with a codebase into which twelve people contributed at the same time. We haven’t been truly working in the same areas, but still, it was the same “new” product. While working together is material for another article, the fact of multiple people involved is a factor contributing to the badness of the code.

Background

Beginner programmers and — what I’ve learned later — some long experienced programmers either — tend to think about software not in terms of the structure, but in terms of data and logic flow.

Let’s consider the following simple problem: create a feature that converts a string of letters into a number based on the phone keypad’s relationship between letters and numbers. I strongly believe phones with physical keypads aren’t thing of the past yet, so everyone understands the problem. Let’s consider the solution on diagrams and compare two ways of thinking about the solution.

Visually the difference is as follows:

Diagrams to compare

On the left, there is a UML illustration of the solution structure, on the right simple flowchart of steps required to solve the problem. They’re not entirely orthogonal, but beginners rarely start to think in the left terms, prefer thinking in the right terms. Thinking only in the right terms leads to bad code.

That way of thinking is typical for the initial cracking of the problem and potentially for some competitive programming, however, the latter isn’t my area of expertise. Can we write working code with this approach? Yes, we can. Can we maintain code written with this approach? That’s doubtful.

Being honest require to say that for a very long streak of years programmers were happy with writing purely procedural code and — some of them — managed to retain maintainability. Buy discipline was required then and discipline is required today. Things considered acceptable by then in bulk aren’t acceptable today, let’s take global variables for example. Doesn’t procedural programming mean bad code then? No.

Bad code

We don’t have space in a single article to discuss all possible tools to achieve the bad code. Instead, let’s focus on direct derivation from the thought flow described earlier. So the first tool in the arsenal of the bad code writer is long functions. And next to it is avoidance of clear separation of concerns. The third one is reinventing the wheel.

So, to start writing bad code you can start with making sure your functions are long, longer the worse. The general concept here is to put as many variables and conditions as possible. Let’s consider a small example to start with:

Simple example

Is this really bad code? We deal with a simple problem, so we have simple code that works. So it’s not as bad as it could be for a little more complex problem. What are indicators of bad code in this example?

Without going down to the efficiency of Ruby, structurally this code does everything all together. Mixing concerns of tiny problems that could easily be extracted from it, like finding the digit for a letter, is a straight way to produce a bad code.

If we’d consider the tiny reinvention of the wheel we did here, the search for the element on the array is part of the core library. Not using tools at hand (except in some really rare circumstances) leads to bad code. Taking responsibility for in-house implementations of basic algorithms without proper testing is a bad code either.

Worse code

Let’s make this example more complicated. Let’s convert not only letters to digits, but revert digits to letters either:

Bidirectional conversion example

We just had to deal with the change of requirements. A pretty standard situation, right? Right. But the result is even worse code. Now the reader is unable to tell what this code does without a deep analysis of all code paths. Great! We’re getting better at writing bad code and increasing our job security.

Clearly, we don’t apply any obfuscation here, but we have to have a chance to return to this code ourselves… at least for some time.

Growth over time

The above demonstration of stepping up in the incorporation of a new requirement is just a tiny example in comparison to the typical growth of commercial codebases. We need to multiply many times by size and time to picture the complexity and illegibility of the growing code. Simple examples like above only scratch the surface, but nicely demonstrate the right direction in making the code bad and worse later.

There are software engineering practices recommended to apply intended to reduce these effects, but these are countermeasures a bad code writer would steer clear from. You can find plenty of articles about refactoring around if you’re interested in knowing your enemy.

Summary

If you want to write bad code, keep style compact, don’t split into functions, use short cryptic names for variables and functions, nest many levels. That’s the first step in mastering bad code. Bad code doesn’t mean wrong or incorrect code, just a lack of positive stylistic features and missing abstractions.

Many of my colleagues say masters of writing cryptic code are programmers coming from competitive programming. Tight schedules to solve problems during competitions force them to focus on a solution, not on the design — the code often reflects just the shortest path between thoughts and working pieces. I’m not experienced in competitive programming, but I’ve seen code written by some good competitive programmers and — believe me — it was bad.

If you liked this article, if you had the fun of if you were annoyed, even angry, maybe disappointed, but you’d like more of these emotions reading, please let me know in the comments. I’m considering writing a book in the same theme covering skills in writing bad code in a much wider scope. I’m interested to know if at least one person would be interested. Thank you for your time.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Michał Fita

Michał Fita

Software Craftsman who started programming before even had a computer.