Lint Early and Lint Often
Some of the lowest hanging fruit you can pick for an easier to maintain project is setting up and automating linting on every check-in or pull-request as early as possible. It should be one of the first steps in any build pipeline and often serves as an early indicator if you’ve tried to push something obviously wrong quickly. Linting will prevent a lot of unnecessary dings on pull-requests and wasted engineering time having to point these things out as well.
What kind of code should you lint?
Anything in your code base that is being used or will be in the future.
- Application code? God Yes.
- Configuration Management code? Like chef recipes or ansible playbooks? Yes.
- Unit test code? Integration test code? Selenium test code? Yes to all.
- That random shell script that got checked in a year ago to automate something but we never finished? Yes. If shell scripts are part of your project’s workflow in any meaningful way, then that shell script should’ve been linted when it was checked in with the rest of them. A good shell linter is Shellcheck.
But what if our repository has code written in multiple languages? Yes, linting is needed even more in this situation. You and your team members are not likely to be touching all the of the codebase every few months and they won’t all be domain experts in every language either. They’re still capable of contributing but will need a helping hand remembering the anti-patterns and style conventions. Have at least one linter running for each language on any code of value.
Your projects sanity. Your teammate’s sanity. Your own sanity.
Adding linting becomes increasingly harder to do as your application grows and ages. Don’t believe me? One day you or a teammate will probably get fed up of some unwieldy code and decide to download and run a popular linter on your project. The excitement will turn to anguish when hundreds to thousands of linting errors are seen on the first run. It’s not usually just trailing white-space or missing new line failures either, it could be bad control flow or dangerous unintended use of certain methods that will need to be refactored. It likely won’t be easy to fix and creates a risk of introducing bugs as you try to. Large and difficult to review pull-requests go up which take a while to get reviewed and potentially create merge conflicts.
If it’s hard enough to get that change reviewed and deployed safely, that once ambitious engineer will soon run out of time and the change gets shoved down in priority. The pull-request will be left hanging, any who try to pick it up again will be doomed to encounter more merge conflicts and pain the longer that change is not merged.
Every time they have to look at the poorly formatted code, it will be a reminder of the wasted time and effort. It will hurt until they stop caring and we don’t want that, neglect accelerates software rot faster than anything else.
Another issue is checked in code might be copied and used as an example by a developer in the future, even if we don’t intend for it to be. This means that poorly formatted code will be seen as gospel to the unfamiliar eye. The software rot will start to multiply as others follow suit.
Any linting is better than nothing.
If the linting rules are too strict for your team, agree to sane exceptions as a team that you will be able to live within the long run and configure them in the linter. Line lengths are a common exception. Remember that anything you tolerate will get into your codebase and become more difficult to change later.
To prevent your own future maintenance disaster, lint early and lint often. It’s easier to keep code clean than it is to clean up the dirty code. Lint on every commit if you can. Not just for your projects maintainability but for the sake of you and your contributors, everyone deserves to have some pride in the code they write and ship. Good linters give you the fast effective feedback to keep your teams code inline with agreed-upon conventions and help them write better code as they learn those conventions.
Make it part of your project bootstrapping process. Earlier you start doing this the better.