On constraints: 80 columns

Josh Bruce
8fold
Published in
10 min readDec 2, 2017

--

This is planned to be a series and will be somewhat philosophical in its approach; however, it is pragmatic in its intent. Further, we’ll be focusing on software development; however, I believe the abstract concepts and principles are applicable elsewhere.

In software development we have had, and continue to have, debates over coding style since pretty much the beginning.

How do you layout code? Tabs or spaces? Where do you put the curly braces? To comment or not to comment? What do you name things? 80 character line length or 120 (or infinite for that matter)?

Back in the day one of the arguments for an 80 character max length had to do with the constraints of a terminal window and the difficulty in scrolling to the right; or, it had to do with the IBM punch cards from really long ago. We don’t have this externally imposed constraint anymore.

So, the 80 column thing is arbitrary now, yeah? Something held over from the dark ages of software development. A level of bureaucracy no longer necessary in the modern age.

I’m not sure I agree and I think, for me, it starts with our perception of constraints.

If we look at constraints (laws, rules, standards, whatever) first as being put in place to hinder progress, something getting in the way of freedom, then our bias would probably be to say, “Yes, stop imposing or following that constraint.”

Having said that, one of my favorite quotes on constraints comes from Andy Rutledge (it’s not just this line, but the surrounding bits as well):

Constraints are a designer’s best friend. They’re signposts, not shackles.

“But software developers aren’t ‘designers’,” you might say. I would offer the following syllogism in response:

  1. Uncompiled code is written for humans to read and understand in order to make informed decisions about a future state.
  2. Compiled code is written for a machine to read and understand in order to make informed decisions about a future state.
  3. Therefore, if you use a compiler, you should write code for humans, not machines.

This article is analogous to uncompiled code. You traverse it in an effort to tease out meaning; you are the compiler. Then there is a side-effect, positive or negative. (You walk away, give it a clap, it changes your life profoundly for the better or worse, which is a stretch I’m sure.)

My assertion is this, whether you are writing for a human or a machine, you are designing your code:

purpose, planning, or intention that exists or is thought to exist behind an action, fact, or material object

Whether talking about software development or not, we are all designers to some degree. (I design my life, for example.) Therefore, we can appropriate the sentiment from Andy for our own purposes.

You are writing code in such a way as to gain the best possible outcome within the constraints you find yourself in. (When you work with or for other people, I would propose that you should take their constraints into account as well and make them your own.)

When I write pure, uncompiled client-side JavaScript with the intent of delivering that code over an internet connection, I tend to write it as close to the machine as I can without losing meaning for myself. What that means is no comments. Short names for most things…why say in five concatenated words that which can be expressed in one. (Notice Counter in the following example is not USPopClockCounterSingletonForTimingAnimationEvents, for example.)

The following example is a piece of JS I wrote a few years ago that did go through “minifier,” which mainly just shortened variable names, not a full compiler:

Arguably, I could have made it closer to the machine by removing the whitespace and putting it all on one line. I could have built a table mapping a short string of characters to the human-friendly versions and stored outside the program for future reference. And, if I could not maintain the download time constraint we had, I would have done so.

Having said that, if had done so I would have become a compiler, but more importantly, I would no longer be able to grasp what’s going on (in some ways I still can’t, it’s been a while since I looked at that code; mainly I don’t remember why I needed a counter and I’m wondering if I could remove it).

The point is, there are a lot of constraints (or restraints) imposed when writing an uncompiled language for the web, which has three primary interpreted languages (HTML, CSS, and JS). Disk space being one, we might talk about that later. Internet bandwidth is another, we might talk about that later. The hardware limitations of the device the code is run on, we might talk about that later. The other constraints we tend to impose on ourselves.

The 80 column thing is one of the constraints we impose on ourselves; despite it starting as something imposed on us.

PHP, like JavaScript, is an interpreted language; don’t worry if you don’t fully understand the technical backing of that…I don’t really understand completely myself (I tend to just say uncompiled). What makes PHP different than JavaScript though is that I can know the constraints imposed by the hardware because the code is run on a machine I control either fully or partially and I don’t have to transmit the PHP code over the Internet, just a resulting string. Therefore, my primary mission is not to keep my code as small as possible (unlike with client-side JavaScript); instead, my primary mission is to make the output (the HTML) as small as possible; therefore, I can write my code more for a human.

Here’s a piece of PHP I wrote for a human:

What makes this written for a human and not a machine?

Let’s consider the 80 column is a dinosaur argument again. All right, granted. The externally imposed constraint of punch cards and terminal windows is no longer there. Having said that, there are two things to realize.

First, the “it’s old” argument runs close to the fallacy of the single cause. Second, now that we don’t have an external “oppressive” force imposing its will on us, what other reasons exist that would make you want to keep that constraint around?

The longest line in the PHP example above is line 26. In the production code it ends literally on column 80.

I propose that when we write code for humans, we become designers, typesetters, and authors of prose for ourselves and others. Not in the sense that we should do that, but in the sense that it happens by the mere act of writing code for humans.

So, what’s it like to read like a human? (Gotta put the user experience hat on.)

  1. Optimal line-length is 40 to 75 characters (most often we shoot for 60): So, 80 (or 88) gives you a 60 character line with up to five tabs for a four space tabbed language (traditionally PHP and similar languages) and 10 tabs for a two space tabbed language (traditionally JavaScript, I’m not sure if this tradition in JavaScript is to conserve file size or not as it’s one of a very few languages that traditionally uses two instead of four). We tend to use tabs to separate blocks of logic (paragraphs, then sentences in a paragraph). So, a class has no tabs, a method has one, a conditional inside that method is two, a loop inside that conditional is three, a switch inside that loop is four, a loop inside that switch is five…in PHP I’ve hit 80-ish characters, in JavaScript, I’m only half way there; that is, if I’m writing sixty non-whitespace characters per line…having said that, do you remember where you are inside the code? Which brings us to…
  2. Optimal hierarchical depth of information to maintain contextual awareness (also known loosely as information architecture): That’s a really annoying way of saying humans easily lose their place in hierarchies, “What was I talking about again? Oh! Right, 80 columns.” We’re talking writing here; so, let’s consider the following concept and constraint. If we consider each tab to represent a different idea in a document (like the document itself, a section, a paragraph, and so on), let’s compare that to the constraints of written communication. Word from Microsoft, by default, has six-levels of header styles; if you want to go beyond that, you have to create your own. The American Psychological Association Style Manual recognizes five levels. Medium itself allows for two (and you cannot have multiple depths for lists). The typical recommended limit from the User Experience profession is three to four maximum. So, if you’re writing code for a human in such a way as to require more than 80 characters (including tabs), there’s probably something else going on there. (Could be your former employer judged you based on writing as few lines as possible; thereby, incentivizing you to use a variable assignment followed by seven or eight ternary operators; instead of using a conditional or switch. The intent of law was to make code concise and small, the resulting anti-pattern was to find clever ways to write a single line describing a complex concept.)
  3. Consider the audience; who are you writing this for: Sort of the crux of this article really. Computers and mathematicians understand math E=mc², humans understand language, “energy equals mass times the speed of light squared.” This article is written for humans with a basic understanding of software development languages. The PHP function above is written for the same. Having said that, the hasRole() method is written more for a computer or mathematician: return (strlen($this->_role) > 0);.
  4. Consider the audience, continued: There’s a world of difference between an expert in a domain and a novice. If you are the author of a system, you are the expert. You know how it works. It’s all in your head. If you’re new to the project, you got nothing…and it can take forever to get up to speed (how long does it take for you to on-board a new team member, the longer it takes, the more likely your code isn’t written for humans outside of the original creators). In traditional writing we can equate this to the Flesch-Kincaid readability scale. The more machine-like your code, the higher I tend to put it on the scale; for example, slide 19 of this presentation by Sean Parent…it’s not completely off the charts, but it’s not really entry-level stuff either. If you’re writing your code in such a way that you are the only one who can understand it, you’re going to find yourself pretty annoyed later as people keep asking you how it works (because it’s not as self-explanaatory as you might think) or asking you to fix a defect (because they can’t just fix it themselves) or asking for a new feature (because they can’t just write themselves). The farther from the machine you get, the easier the code becomes (this too can go too far); HTML is a pretty dead simple language to pick up and easily read later…XSLT, on the other hand, takes a bit of work. So, consider who the next person in line for your code is; are they a super duper power user with complete knowledge of your codebase, or the new guy fresh out of high school? For the web (and medical lab studies) the target reading level is about the first to fifth grade. Read that again. Now consider your codebase. Could someone, “fresh out of school” grasp what you’ve written? (Oddly enough, I’ve gotten into the habit of actively forgetting every line of code I write pretty much the next day. If I don’t understand it when I come back, I didn’t do a very good job of writing it. Therefore, I’m always the new guy on the project, and I’m also the guy whose brain isn’t filled with all that code, leaving space for more important and silly things like random movie quotes from the ’80s.)

There are a lot of other design patterns and principles that come from this simple 80 character constraint. Vertically long methods are harder to write because you can’t keep putting conditionals and loops inside of them…at least not without either going beyond the character limit or not tabbing your code at all.

You can end up with anti-patterns as well — what I classify as localized spaghetti code, for example, where breaking things into methods results in a local method calling another local method, that calls another local method, that calls another local method, and so on, before maybe returning something and by the time it does you don’t even remember why you called the first method to begin with.

The revelation of anti-patterns leads to the discovery or adoption of new constraints; each method should return almost immediately, or create one side-effect before returning (either void or something else). Those new constraints can reveal new anti-patterns; and repeat.

Software engineers are clever…their specific type of cleverness tends to revolve around circumventing rules and constraints in unintended ways, to be quite frank…that’s sort of the underlying skill that comes with hacking and cracking and bending computers to our will…the technology to do what you want doesn’t exist (constraint), I will do it anyway (ingenuity, creativity, and cleverness). I’m only half kidding when I say, if you want to know how to break the intent of law, without breaking the rule of law, find a software engineer.

The hard part is walking the line because you can be too clever, which tends to cause negative side effects both in and out of your code.

I have found the better I get at communicating in prose, the better my code written for humans becomes. I have found the better I get at logical argumentation and debate, the better my code written for machines becomes. When using good writing and document design principles on my code, the 80 column constraint is no longer a shackle, it’s something I never hit in the first place; but I really like having the signpost that says, “Hey, you might not understand this problem well enough yet.”

As a side joke, it’s possible to write code that is neither for machine nor human. We see it all the time in fact. Especially on the Internet because the cost of access is so low (you can write a fully functional application in Notepad using the base web technologies). God knows I’ve written my share of this non-human-non-computer code. But, we’ll skip talking about that for now because it’s not a problem that can be solved by talking about writing/coding style and constraints, I don’t think.

Which topic should be next?

Highlight or comment to place your vote; or, comment to add a new constraint topic and I’ll add it to the list.

For the human developers in the room:

if (highlights > 0 || comments > 0)
sortedTopics = proposedTopics.sortedByVotesDescending()
nextTopic = sortedTopics.first()
else
nextTopic = proposedTopics.first()
josh.writeArticleOn(nextTopic)if (comments > 0) foreach (comments as comment) topics = comment.topics()
proposedTopics.add(topics)
  • Comments versus self-documenting code
  • Internet bandwidth
  • Disk space
  • Hardware limitations
  • Styling function argument lists as a list versus dependency injection frameworks and factories

--

--