I was recently on the Front End Podcast (Listen to it here) with Rob Kendall. We discussed something I'm quite passionate about. Making code better! This means how to follow best practices and coding standards we have assigned and how we can do all this quickly, easily and (most importantly) automatically. So what's the secret I hear you ask! What is this magic silver bullet!
The Secret? Use a Linter!
This Static Code Analysis tool is a powerful way to keep your code in line with the latest standards and to keep a shared codebase following a set of chosen principles. We'll run through the what, how and why's explaining how you should go about implementing this solution in your code today.
The term "lint" is derived from the name of the undesirable bits of fibre and fluff found in sheep's wool.
What is it?
Linting is the name for the process of checking your code against a set of pre-determined rules. Whether those are language dependant or specific to your project. Linting will run a program or tool that will analyse the code for potential errors. It will make those warnings or errors clear to you and give you the option to fix them.
Linting tools are especially useful for interpreted languages like JavaScript and Python. These languages lack a compiling phase that would usually throw errors prior to execution, and you can feel a big benefit when using it in these instances.
The Linting Tools Available to use.
So now we know what it is? How can we use it in our project? Surely we need a linter specific to each language! Well, you're right! But luckily, every major language already has linters available for them, and some are even language agnostic.
You can find a detailed list here: https://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis
A nice curated list from the above would comprise EsLint this is a popular Linter for JavaScript which you may have heard of, or may already be using. SonarQube is a popular language-agnostic option that works from Java to PHP to Python. C# and .Net in general has StyleCop and FxCop which are often used together.
So, you might have heard of some of these already, but what are the benefits of using this, why should you invest your time to add these tools to your solutions?
Some of you may be thinking... what about Prettier? Prettier is not really a linter, as it doesn't check code per se. Prettier is an opinionated code formatter. It saves you time and energy and stops arguments about line length, bracket placement and most importantly, "Tabs vs Spaces".
The best thing is you can tailor it to your needs. It can be run during development or added as a step when committing to your source code repository. It's flexible enough to work around your situation.
Why should I use it?
Everybody wants to write clean code, they want to follow best practices, they want to keep up to date with the latest and greatest ways to create code.
Linting is important to reduce errors and improve the overall quality of your code. It also helps to make your code consistent over time, and across teams and individuals. It's great at catching problematic bits of code early on, and in most cases, lets you know how to fix them! Let's look at the pros and cons.
Linting Strengths.
Linting will flag up any unused variables in your code. Any potentially unreachable bits of code! (Did you test an if statement by changing the logic to a 1 == 1 comparison?) It can also help to find issues with indexing beyond array lengths.
It will catch errors early, we all know the best time to find a bug is during development. The longer a bug is left undetected and unresolved, the costlier it is to fix.
Linting Weaknesses.
Linting can produce a lot of errors and warnings. Sometimes as many as there are lines of source code. This can lead to a lot of false positives and may deter you from fixing what is really important. That's why setting up the rules, to begin with, is crucial.
Linting will identify violations of best practices. It won't teach you those best practices. Developers can use linting to improve their code, but they might not replicate the standards that are advised.
Linting is inexpensive in actual time and cost, but it can decrease developer productivity, as they fix or alter the code to conform to these rules.
How to enforce it?
So this is the tricky bit. As we can see, there are pros and cons to the notion of linting. Do you want to get your product shipped quickly or conforming with best practices that may speed up future work? There is always a trade-off, and this is something to remember.
Do you expect your team to fix all the issues every time they change something? Should they just have to keep what they have changed tidy? Maybe you just want to inform them, hoping they make any relevant changes?
The Happy Medium
What I've found is that some level of linting is useful, especially in unison with a code review process. Having basic things fixed before they go for code review means generic checks are no longer made by the human eye. It also allows us to focus on the important aspects,rather than the subjective.
We should check if we can refactor the code? Whether it would benefit from being split up, either into different files or functions? Is there sufficient documentation? Do we have tests covering important functionality? Is it scalable and secure?
I like to think that we should all follow The Boy Scout Rule - making sure to leave any code we touch code better than we found it, this means we will gradually remove any technical debt without having to do it all at once, or as specific tasks.
Leave your code better than you found it.
The boy scout rule
My JavaScript Setup - The Trifecta
As I mentioned above, JavaScript benefits greatly from the introduction of linting, but as the language is so open, putting in some guidelines is a necessity. Here is the configuration I add to my solution to enforce linting during the development process.
I use 3 external libraries to aid me in my endeavours.
- Husky is the easy way to configure Git hooks. For those that do this manually, having it all set in the top-level config, standardises and simplifies the process massively.
- The next is Lint Staged. As mentioned before, you want your developers to have a happy medium of what to fix. If they are working on a file, I think we should all follow the Boy Scout Rule, meaning we clean up the code before resubmitting.
- Last, but not least. Pretty Quick will run your Prettier settings on all staged files. It's similar to Lint Staged but taking care of the formatting instead.
Install and Configure Packages
So anyway, once you've installed the three packages, you can add the following lines to your package.json. This will lint all your JavaScript and TypeScript files if you're using any, and format your staged files before committing. If the linters throw any errors, we display them to the user and block them from proceeding!
The Configuration - Package.json
The sections above add the tools installed into the Git pipelines. Husky is our middle-man and you can see that in its hooks section the pre-commit hook is configured to run PrettyQuick on our staged files and also the Lint-Staged section afterwards. This runs eslint and tslint on the globs specified, which in this case are all staged .ts and .js files it finds.
Lastly, we must set up the rules, we want to use during this process.
TsLint Config
The important things here are the rule sets we are extending. tslint:latest and tslint-angular are taking care of the fundamentals. We can overwrite any of these base rules below, and I would recommend finding that happy medium for yourself. I have left a couple of rules that make sense for me.
tslint-config-prettier is required so tslint does not format our code, that is Prettiers job and where the prettier config comes into play.
Prettier Config
The best place to put your prettier config is a .pretterrc file. I have shown a simple set of rules to get you started. The Prettier Documentation of Configuration is the best place to look for tailoring the setup to your needs.
The outcome?
Here it is in action. You can see a git commit kicking off husky which in turn runs our tools! First Prettier fixes up any formatting, before eslint changes the let to const as it's never reassigned, and moves our class level declarations to the top of the file! Pretty neat right!
So in conclusion, hopefully, you've understood what linting is, why to use it, and how to adapt it to your coding environment!
I would love to hear of any other setup that works for you! There is always room for improvement. Please share your thoughts below!
Top comments (4)
Most development teams enforce some sort of linting rules, usually after a pitched battle over tags versus spaces, and where to place opening/closing braces (I kid you not).
Once you have established the linting rules, any professional development team then requires unit testing. It's a pain at first, but research shows unit tests return about a 30:1 ratio of time saves discovering and fixing bugs.
I feel like linters are more for improved maintainability and readability of your code.
You can write bad, code run a linter, and still end up with bad code.
I think the real benefit is in SCA tools like SonarQube or Coverity, which analyze cyclomatic complexity, code smells, technical debt, known security issues and much more.
And the ultimate code quality practice... code review!!😁
That’s how, in my opinion, you improve your code quality effectively.
Still, great article! Do you use any other tools besides linters?
Hey, Thanks! There's definitely a whole suite of tools available. I've used a variety of them and think they are all valuable in their own way. I agree you can never beat a good quality code review with a peer though!
Yes! Lint Staged and Husky are my code law enforcement! So grateful these tools exist. :)