Automating your Coding Standards

Here at Etch, we use a little collection of tools and a sprinkling of workflow to make our lives easier, and keep our codebases cleaner.

Josh Rose
Etch
4 min readNov 15, 2016

--

Nicely formatted code makes developers lives easier, and reduces bugs. Consistent variable and method names, spacing, and even brace positioning all make it easier to scan through code, meaning you spend more time looking for bugs, and less time grumbling about indentation.

Most software houses will have a coding standards document somewhere… but normally enforcing this is left to individual developers. And we’re all fallible. Machines however, are much better at enforcing well defined rules, so we can use them to automate the enforcement of coding standards.

Linting

Linting is the process of automatically checking your code for stylistic and programmatic errors. A linter is the program that carries out the linting! Simple really.

We incorporate linting into our build scripts, as we treat linting as part of the build process.

Getting started

An example base gulp build

As you can probably guess from the above image, this project uses PHP, SCSS, and JavaScript.

We’re using eslint for JavaScript linting, sass-lint for scss linting, and php-cs to check over our php code.

To make things easier to maintain we keep our task files pretty lean and import all the config options from a config file.

Finally, in our index.js file, we have a gulp task that pulls all our linters together:

gulp.task('lint', (done) => {
runSequence('eslint', 'scss-lint', 'php-cs', () => {
done();
});
});

We ran into some problems with php-cs if it wasn’t the last task run, so we enforce the order with runSequence to make our lives a little less confusing.

Locking down the configs

There’s no point using these linters if we’re all using different configurations for them, so we check in our config file for eslint. There’s a lot going on in there, so I’ve commented each line to make it easier to understand.

{
// The airbnb config happens to do most of what we want:
// https://github.com/airbnb/javascript, so we pull that in
// as a starting point
"extends": "airbnb",
"plugins": [
// We use a lot of react, so we've added a plugin to
// handle react syntax
"react"
],
"env": {
// All our JavaScript is es6 compliant, and we need
// to tell eslint that
"es6": true
},
"parserOptions": {
"ecmaFeatures": {
// Enables support for https://github.com/sebmarkbage/ecmascript-rest-spread
"experimentalObjectRestSpread": true
}
},
"rules": {
// Always have braces around a function body to make
// it easier to read
"arrow-body-style": [2, "always"],
// We disable this because the styleguide generator
// we use breaks with stateless components
"react/prefer-stateless-function": 0
}
}

And for sass-lint:

files:
include: '**/*.s+(a|c)ss'
options:
formatter: stylish
merge-default-rules: true
rules:
class-name-format:
# We use hyphenated BEM because it’s easy to lint, easy to
# review and fairly strict. It also means that if problems
# do arise they are smaller and more self contained, so easier
# to refactor
- 1
- convention: hyphenatedbem
id-name-format:
- 1
- convention: hyphenatedbem
nesting-depth:
# Set the max nesting depth to four. It defaults to three, but
# we find four is a more realistic setting
- 1
- max-depth: 4
placeholder-name-format:
- 1
- convention: hyphenatedbem
# Only treat property sort order as a warning. Sorting
# properties can have some impact on gzip compression file
# size, so we clean this up before go live, but for day to
# day development, we don't care
property-sort-order: 1

For PHP we use the PSR2 coding style guide, which is designed to “reduce cognitive friction when scanning code from different authors” (i.e. make it easier to read your PHP), withPHP_CodeSniffer, which is set in config.js.

Hook into Git

As we use git for all our version control, it makes sense to tie into it for running our linters. Luckily git provides you with a selection of hooks, events that link in with git commands like pull, commit, and push, that you can “hook” into to run scripts.

To save us having to remember to set those up with every new project, we use a little tool called husky, which uses package.json to manage the hooks.

Once we’ve installed husky, we add the following to our package.json:

"scripts": {
"precommit": "yarn run lint",
},

Tada! Now when you run git commit, the linter runs, checks your code, and if it fails any of the linting steps, it cancels the commit, and gives you a pretty readout of the errors it found so you can go back and fix your code before trying again.

Powering up

Once you’ve got this far, you’ll probably realise the power of git hooks, and start using them for all sorts of things.

We have post-merge and post-rewrite hooks that install dependencies and migrate our databases, and a pre-push hook that runs all our tests and cancels the push if they fail.

We also use validate-commit-msg on the commitmsg hook to ensure we have a nice, easy to read git log to scan through.

Go Forth and Lint

We’ve covered a fair amount in this short post, but hopefully it’s piqued your interest enough for you to want to get out there and try it out. There’s a small gist containing the files mentioned above, that should be reasonably project-independent (you’ll have to create your own directories though).

For some super-powered up linting and git hooks usage, you should check out our laravel boilerplate, which contains all the above and more!

Excited by clean code? Want to work with a team that’s passionate about what they do? Get in touch at hey@etch.co, or check out our site.

--

--

Josh Rose
Etch
Editor for

I build progressive web apps for @etch. React + GraphQL + DataLoader 😍 https://joshthewanderer.com