Writing Code that a Computer Can Understand Is Only Half the Job

(Part 2 of …11?)

One of the most important, oft-overlooked aspects of writing code for early projects is establishing and maintaining well-formatted, readable code. And, for many of you, this is not the first time you’ve been scolded on the importance of linting your code.

It can be hard to see the benefits of editing code for (human) readability when you’re a small team, in a small office space, just trying to get a working MVP in front of your customers. But the virtues of establishing rules for code format and style and automating the enforcement of these rules — so called code “linting” — have been well established. I’m sure you know that a coder spends far more time reading code than writing it, and that reading code with multiple formatting styles and competing logic patterns costs more time and money than spending the extra time to write clean, well-formatted code up front, so I won’t dig too deep into the reasons to lint. Instead, here are a few pointers for establishing well-linted code in your codebase, particularly if you’ve inherited a codebase with a variety of formatting styles and patterns.

Analyze the Existing Code First

If you’re looking to lint an existing codebase, before installing and configuring a linting tool you should analyze the existing code and look for already-established patterns and formatting styles. The goal should not be to get everyone’s code looking exactly like yours, but rather to just get everyone’s code looking the same. So if all of the code already uses four spaces instead of two for indentation, it’s reasonable to suspect that the developers’ IDEs are also configured for four spaces. It’s probably a good idea to maintain that standard (although, personally, I’m a big fan of 2-space indentation, which allows you to view more code on your screen at a time… but that’s an argument for another article!).

If you are insistent on using a particular formatting style that is definitely not already being used in your codebase, make sure you have a tool that will enforce the rule for you, and that you’re in a position to make sweeping changes to your entire codebase without causing a disruption. At BetterCloud, almost all of the JS code included semicolons at the end of each line, but I felt strongly about saving the extra keypresses (no, you don’t need semicolons). However, if I hadn’t had a tool that would safely and automatically remove these semicolons, I wouldn’t have attempted to establish this standard.

See What the Community Is Doing

Though no two codebases have the exact same set of formatting standards, each programming language tends to have its own ecosystem of tools, experts, and best practices. You can often find a recommended style guide for the language you’re working in. Just as often, you can find ready-made configurations that enforce these styles in a variety of lint tools.

At BetterCloud, we use eslint for analyzing and enforcing our lint rules, and we used the Airbnb JavaScript Style Guide as a jumping-off point for our own code style. We tweaked some of the rules to match our existing incidental standards but for the most part, we follow these rules closely. We also use Prettier, a tool devoted to code format and style (unlike eslint, which also includes rules for best practice logic and syntax patterns). Prettier is quickly becoming an industry standard itself, and I recommend using a mix of eslint and Prettier.

Use Tools to Enforce Rules (If You Can)

If you’re trying to enforce a pattern or formatting style without a lint rule to automate the enforcement, you’re going to have a bad time. It doesn’t mean it’s impossible — careful PR reviews can be used to enforce anything — but human-enforced rules are bound to be ignored or forgotten. A PR review with many formatting change requests can also be tedious (and intimidating).

Luckily, custom eslint rules are often easy to write and integrate into your existing configuration. I highly recommend taking the time to write these rules if your team finds them useful for maintaining code quality and they don’t already exist.

In the end, code review is your last line of defense. If you have a pattern or preference you want to enforce but you do not have a lint rule and cannot easily create one, make sure you consistently mention this change request in your code review comments.

Choose Your Battles

Like many things in life, writing and maintaining a codebase is a team effort and so requires compromise. If you find that a particular rule is generating a lot of pushback from the team, consider changing it. Perhaps it’s a rule that the community as a whole is in agreement on, but for some reason — cultural, historical, etc. — your team doesn’t subscribe to that particular line of thinking. If that’s the case, ask yourself if the battle is worth fighting.

Remember: the ultimate goal is to make the team’s code look consistent, follow the same quality standards, and essentially seem like it came from a single author. Your personal style is not necessarily the model for this, so make sure the team has a voice in shaping these standards for the rules that don’t have high stakes or a clear logical basis.

Delineate Between Errors & Warnings

When enforcing rules, it can be helpful to distinguish between rules that will generate warnings and rules that will generate errors. This distinction places a level of importance on the issues addressed by the rules and communicates this importance to your team. Such a distinction can also be used to aid automation at varying levels of enforcement and help ease a team into a particularly difficult-to-follow rule.

For instance, you may have a new rule that most of the team habitually breaks, but it’s not one you want to let slide. In this case, it can be helpful to classify the rule as a warning first, and then, after some time has passed — and with ample notice — this rule can be “upgraded” to an error.

At BetterCloud, it wasn’t uncommon to see “magic numbers” crop up in the code. These are numbers (other than 0 or 1) that are passed directly into a function rather than first being assigned to a well-named variable. By not assigning these numbers to a variable, the meaning and purpose behind the numbers was not clearly communicated in the code, and so these numbers are what the community calls “magic numbers,” because a reader might see them and have no clue what their function was. We created a rule to disallow magic numbers, but because the code was already littered with them and the teams had a habit of regularly creating new ones, we decided to make this rule a “warning” and set a cap on the number of allowed warnings. We encouraged teams to fix handfuls of their “magic number” infractions at a time. As they corrected these, we then lowered the allowed warnings cap to wean them off the practice of using magic numbers. Finally, we were able to upgrade the rule to an error and ban magic numbers entirely.

Set Sensible Issue Caps

In addition to classifying some issues as warnings, for many lint/build integrations you can also set a cap on the number of allowed issues of a particular type. Typically, this takes the form of “0 errors allowed, but x warnings allowed,” but it can also be configured to only allow y number of warnings for a particular rule. This allows you, for example, to more easily wean a team off of regularly breaking a rule by slowly lowering the warning cap for a particular rule until it has reached zero, at which point you can update the rule to “error” (which should already have a cap of zero).

Lint, But Listen

In the end, it’s important to use common sense in your approach. If your team is particularly averse to linting, it may take more convincing and a slower ramp-up. If your team embraces the idea, perhaps it’s better to set aggressive rules and caps from the start. All teams are not created equal, so it’s important to listen to the needs of your team and adjust your expectations accordingly. But don’t give up! Linting is important and, though the benefits aren’t always immediately obvious to a team who isn’t used to the idea, it doesn’t take long for those benefits to surface. When the team experiences the benefits, it quickly becomes a habit with an appetite for more. Before you know it, linting will become second nature, and you’ll wonder how you ever got by without it.

Stay Tuned for Part 3!

If you’re just joining us, this is the second article in a series that digs into the ins and outs of the Front End architecture at BetterCloud. The first article can be found here.