I often think back to English classes in middle school, where I learned how to format text to the exacting standards of my teacher at the time. We were expected to have proper tabulation, perfect punctuation, and very specific paragraph lengths, lest we be punished by docked points. It was all a particularly frustrating experience: after all, the meaning of what we were writing wasn’t impacted by these things. I didn’t appreciate what was being imparted, as it seemed like fluff without any substance.
Years later, I encountered a copy of The Alchemist, printed without any capitalization throughout the entire book.
The specifics of why this particular edition was produced is beyond my understanding, and I can find no record of it online, but it has stuck in my mind for years because of just how difficult it was to read. Sentences blurred together, and I found myself reading and rereading parts just to understand what was being said. The book already uses an odd, staggering sort of storytelling, with fragmented half-sentences making up a large portion of the text, and lacking the visual cues of where to stop and start thoughts led to a very difficult and time consuming read.
Considering how difficult such a small change made reading natural English, it’s probably no surprise that unstyled code is orders of magnitude more difficult to understand.
What’s more, unstyled code is much easier to excuse. The primary expectation of a software developer is to produce code that is functional and correct, with the need for code that is maintainable being a far secondary priority. Particularly in the context of contracted development, maintaining an aggressive release cycle is critical to the commercial success of the project. For new projects, especially, the priority has to be getting anything functional ready to demonstrate.
Unfortunately, this usually leads to early code being written off as technical debt, code written as quickly as possible, with a comment that reads “clean this up later.” While this is often done with good intentions, the reality is that technical debt is the lowest priority of any development team, and it’s unlikely to be fixed. What’s worse, unstyled and unorganized code invites a mindset in future developers that “if it’s already bad, I don’t need to worry about my changes being well put together.” Effectively, cluttered, disorganized code is infectious and tends to spread.
So, what’s to be done?
First, a development team needs to make an explicit commitment to code quality, not just in function but also in form. It’s much easier to catch “dirty” code as it is being written, rather than to try to fix it later, but if there’s no consensus among the developers that writing clean code is even a priority, some developers will ignore code quality in favor of development speed, which is always a short-term gain at the expense of the future, since that code will slow down future developers each time they have to read it, even the original author.
Second, dirty code is often an inevitability. Sometimes, massive code reviews will have sections that fly under the radar, or in a moment of panic, emergency code will be pushed to fix a high priority bug. Rather than setting an explicit task to fix the code, developers should have the mindset of a boy scout: Leave the campsite cleaner than you found it. Whenever a developer edits code that is difficult to understand, it’s easy to make small minimally functional changes to clean it: changing spacing and indentation to be more consistent, extracting repeated or complex code sections into separate functions, or renaming variables and methods to be more understandable at a glance. The main difficulty in taking these sorts of cleanup actions is in trying to understand what the code in question is doing in the first place, but if the developer is editing it for another purpose, they have to put in the effort to do so anyway. By making the code clearer, they pay that knowledge forward.
Most importantly, however, is to automate, as much and as early as possible, the enforcement of style guidelines through auto-styling and linting. The reality is that most developers don’t instinctively write code to be readable (though some are certainly obsessive enough to do so), most developers write code to work. Rather than forcing them to devote mental space to remembering the rules of formatting, it is much easier to have an automatic styler to automatically format code as it is written. The two main disadvantages of automatic stylers are that they can take extra effort to set up for a project and that when applied to old files can generate very difficult to read changesets. While there’s no way to solve the first problem, simply establishing consistent auto styling early negates the latter. After all, it’s much easier to maintain clean code when you don’t have to do the work yourself.
Not all changes can be applied automatically, however, and code linters become invaluable in forcing consistency. Code linters help solve styling problems that border on functional issues, like forcing strict typing for clarity or requiring safe scoping of variables. These are issues that can absolutely cause confusion and errors, but can’t always be automatically fixed by a code styler. On the bright side, these issues tend to be far more disruptive, so developers will naturally seek to fix them to prevent errors, provided that they know the issue is there. While linters can be frustrating at times, the frustration they cause is in proportion to the number of errors they throw, so naturally newer code and smaller changesets are far more likely to be closer in line with code quality standards than older code that has been allowed to stagnate and decay.
Code quality safeguards knowledge by keeping the author’s intent as clear as possible, but code quality is far easier to maintain than to build anew. Even worse, it is massively easier to lose code quality than it is to maintain. It takes vigilance to keep code readable, and the earlier you set your standards, the easier it is to actually follow them. It’s easy to write off code quality as a “nice to have”, particularly in the early phases of a project, but it’s worth the pain in the now. Much like athletic exercise, it’s a good hurt: the exercise of appeasing a seemingly needy style guide gets easier with habit and, with the right tools, eventually leads to toned and healthy code. There are always pains at first and there are always excuses for not starting the process of improvement, so don’t wait.