Adopting coding standards within a large codebase

27 June 2019

Over the past month here at ReadMe, we've doubled the size of our engineering organization (…psst) and one thing that we quickly realized was that each of us have our own coding styles. This unfortunately was starting to result in comments on pull requests like "indent this line a few more characters so it's consistent".

Coming from a company that had a 10+ year old monolithic codebase, I am very well versed, with how quickly code can cruft itself if not properly maintained or monitored. We were already using ESLint here for code quality and static analysis, but ESLint can only go so far to keep your code looking sharp and consistent.

Enter, Prettier. Prettier is an "opinionated code formatter" and it does just that. It'll reformat a file you supply to match formatting rules like spaces vs tabs (see: opinionated), line length, comma usage, etc.

Investigation

One of the issues we immediately came to a head with when starting down the path of investigation adoption of Prettier within our codebase was that we didn't want to have one giant, silly, pull request. We neither wanted to do what a lot of projects online do and rewrite their entire Git history. That's a big yikes! We also don't care a whole lot about existing code matching our new coding standards, just that new code does.

Prettier, thankfully, offers two options that we could use immediately:

--require-pragma will look for either a @prettier or @format docblock annotation at the top of files, and if present, will assert Prettier runs against that file. --insert-pragma does the same, but will insert that annotation into the file if it is not already present.

So for new files that are added to our codebase, we can require engineers here to add those annotations to the top of their file for Prettier analysis, but this unfortunately leaves us with a few problems:

None of us are ever going to remember to add @prettier or @format to the top of new files, and we want to avoid a mass changeset with --insert-pragma.

Changes to existing, un-Prettier'd, code is never going to get Prettier'd when we make changes.

What about old code that we're working in though? Unfortunately Prettier doesn't have a way, with --require-pragma, to also specify a list of other files in so we need to hack up a custom solution. Thankfully, since all we care about in this instance is changed files we can use Git to our advantage here:

If there are files that you've edited in your branch, this command will list out those that don't conform to Prettier standards.

One thing to note here is that we unfortunately need to duplicate our .prettierrc configuration in these scripts because our .prettierrc has requirePragma set to true. This automation process is entirely for the purpose of migrating old code up.

A similar command can also be run to include our found changed files in future Prettier assertions as well by utilizing --insert-pragma and --write: