Linters aren't in your way. They're on your side

Traditionally, linters make sure your code is clean and easy for teammates to read. They check for errors, bugs, style, and more. While they are more prevalent in dynamic/interpreted languages, they are not limited to them. Getting code as tidy as possible is the goal, but linters can also take some time getting used to, be a distraction, and might even be impossible to introduce to old, large code bases. We look at why they might still be worth your time.

Article hero image

Linters are continually evolving. At the core, Wikipedia defines them as tools to analyze “source code to flag programming errors, bugs, stylistic errors, and suspicious constructs.” Linting can be seen as a static analysis that happens outside of a compiler; that is, they process and examine source code without compiling it into a binary.

What linters can do for you

Lint tools can be used to:

  • Enforce a style, like pylint for Python or PMD for Java
  • Prevent indexing beyond the end of an array
  • Catch mismatches in variable types
  • Spot potentially dangerous data type combinations
  • Detect unused variables and unreachable code
  • Identify dereferencing null pointers
  • Flag non-portable constructs
  • Monitor for code complexity
  • Detect potential bugs
  • Warn about security issues
  • Finds possible memory leaks
  • Even point towards signs of code smells

Linters vs formatters

Note that it is a somewhat blurred line between formatters and linters, especially since formatters are getting more opinionated for a lot of languages recently. Go ships a built-in one (gofmt), Rust develops an official formatter (rustfmt, invoked via `cargo fmt`), Python's Black is incredibly popular and so is Prettier for JavaScript.

While linters can check formatting and adherence to code style and warn you if you're off, formatters go straight ahead and just apply a preferred formatting and code style completely automatically. Most of the time, the decision to create a more coherent code style on a team will include the introduction of both linters and formatters.

Not for compiled languages?

Yes and no. There seems to be a tendency to reach for lint tools more when you want to check for issues that would otherwise slip through and break things later on dynamic languages, think Ruby, JavaScript, or Python. If you are working in an ecosystem where you can rely on the compiler to catch type issues and other problems, the need is less immediate. There can be benefits for the individual or team nevertheless. If you make use of all above mentioned checks to your advantage, you can:

  • Fix many problems before committing code and wasting time compiling
  • Eliminate bugs before they make it to prod
  • Accelerate the time to market of new features
  • And most of all make developers’ lives easier, with a smoother process

So why isn’t everyone a fan of linters? It’s fair to assume that it is less about developers turning their blind eye to the benefits of linting tools, but rather there are specific circumstances where the benefits are overshadowed by some down side.

What are the cons?

  • The most obvious argument against it is about it breaking concentration. If you are trying to get into the flow and crank out lines of code, a bunch of flags and warnings popping up can take you out of it.
  • Another danger is developing warning fatigue. This is often the result of false negatives and making assumptions about the reliability of linters. If you get into the habit of ignoring all the flags, your linter can protect you as little as the warm, fuzzy-feeling you get inside from gazing at the ever-present check engine light.
  • Using a linter on a massive existing code base is something many would advise against as “implementing a linter on a mature project becomes a tremendous task.”
  • In the same way, early prototyping might not be the right time for clean-up.

In some situations, it might just not be worth the hassle. If you are relying on a compiler to catch potential problems, that is a stronger assurance that code will run correctly. But if you are working in an interpreted language and cannot rely on that ultimate last check, linting tools can be a way to close the gap for your correctness needs.

The myth that “real programmers don’t need linters, they block creativity” seems prevalent, but harmful. With linters evolving, there are good reasons to think about them in a new way. Here is how to be less annoyed with them.

How to change your (team’s) mind about linters:

If you feel you suffer from linter frustration or have trouble convincing members of your team of the benefits of making use of them, here are some ways to think about it more than just as annoying error messages:

How to embrace linters as a team

Let the linter build the bikesheds. Bikeshedding, is when people fall into the trap of discussing something small and trivial around a more complicated project. Tabs? Spaces? Double quotes? Single quotes? Let the linter hoover up all these little style questions before they take up time during pull request (PR) reviews with peers. Get rid of the style questions that are truly not worth arguing about.

The introduction of linters might not only free up time during code review for more important decision making and learning, it might even reduce the number of requests in total. Lint out those that were about style bickery. Standardizing your code is a great way to move the conversation to a more productive level.

Welch Canavan puts it nicely on his blog: “You will never be on a team that is completely aligned on best practices. Part of being a great team member is setting your ego aside and recognizing that it is much more important to agree on a standard than your standard.”

Let the linter create a unified voice. The reality is that code has many (sometimes many, many, many) authors. But the fact that many people have contributed should not be visible in the code. In his talk, Matt Rose describes this as the narrative voice of the writing. You can have oral or written agreements on style conventions to keep this voice consistent but they will never work as well as automatic convention.Your team of many code authors can write with one indistinguishable voice – just like Shakespeare.

Let the linter help keep your code healthy. Code smells, style guide mismatches, security issues or poorly designed code—many modern linters will help you look after your code base’s health. You can see linters as a check-up, a way to measure your code’s health to then discuss in retrospective or architecture meetings.

Let the linter help you automate. Make your life easier and invest the time to automate what can be automated. Most linters are command-line tools first and foremost and thus are excellently suited for automation. Examples are Prettier, Pylint, ESLint or RuboCop.

How to embrace linters as a team as individuals (on a team)

Embrace the learning opportunities. It might be tough to change your mindset from seeing each pop-up not as on obstruction, but, as Matt Eland writes, “Sometimes, just searching and understanding a warning will teach you new things about programming and shore up vulnerabilities you didn’t even know you had.”

Gamify it. If it already feels to you like “you vs. the linter” why not take that to the max. Block out 15-minute of time. And then, much like getting an inbox to zero, see how many warnings you can tackle during this period.

Code drunk, linter sober. Linked to the above, it is all about limiting linters (and potential frustrations with it) to a specific time. If you are in the flow, cranking out that prototype, turn it off. But allow time to address some of the flags before you waste that time with a peer in a review. And of course, we are by no means encouraging having a drink at work. Stay hydrated tho!

Think of linters as a pedantic friend. We enjoyed the suggestion of treating a linter as a weirdly pedantic code review friend. Assume that they know more than you. But since they are your friend, you can also tell them to go away when you’re trying to focus. Just make sure to ask them to come back later to check your code and make you look smart in front of your peers. Note: they are a loyal friend, but take their pedantry with a grain of salt and add your human judgment.

Remember: Linting isn't just for you. It is for the other people on the team.

Linting can help with the heterogeneous knowledge on a team. For juniors, a linter is like an invisible senior team member that points out style guideline documentation, causes them to pause and question steps, and ultimately helps learn a new language. For seniors, it is an easy way to enforce, not their style, but the use of a consistent style on a team. Leading by example becomes more visible and somewhat built in. It saves many shoulder taps and time during code reviews.

The process of linting can be time consuming when starting out a project; it requires the discipline to catch linter messages from your first line of code. It is, however, worth taking advantage of the ways to customize. Make use of best practices. Some companies publish their configuration settings. Like Airbnb's .eslintrc. Github not only published their linter config, but even open-sourced their unified version of over 20 linters last month.

Our parting thoughts are summed up nicely in this contribution “Something I think that programmers don't always appreciate is that linting isn't an either/or proposition necessarily. A linter is exactly like the spelling/grammar checker in your word processor. It's there to advise you.”

Login with your stackoverflow.com account to take part in the discussion.