Linters, Formatters… Same Thing? — Static Analysis Clarified

Linters... Formatters... Aren’t they the same thing? And what is this so-called static analysis? More importantly, does it matter to you?

Let’s dive into the importance of static analysis while developing apps. (Because yes, formatters and linters are different, even though both play crucial roles in our code!)

These automated checks can significantly reduce our workload as developers. Plus, we’ll explore the differences between some of the most commonly used tools today.

Navigation

  1. Static analysis
  2. Linters x Formatters
  3. Husky: git hook
  4. When to use them in a team
  5. Next steps
  6. References

Static Analysis

To understand something, it’s a good first step to look at its benefits and drawbacks:

Static Analysis enhances the quality of our code and, most importantly, its security. Additionally, it helps us avoid wasting time.

You might think it has no downsides with all these benefits, but it can have limited support and a narrow scope. For example, some less-used or less popular languages might face limitations in applying static analysis in their cases.

After looking at both perspectives, let’s dive deeper into this analysis: it consists of a series of automated checks performed on the source code.

Check out this part of an article from The ReadME Project:

Static analysis is a type of tooling that examines your code without actually executing it. This strategy enables static analysis tools to efficiently evaluate your code and provide suggestions for improvements in real-time, sometimes as you type in your code editor.

Seems really useful, doesn’t it? 🤔

Static analysis provides an understanding of the code structure and helps ensure the maintenance of standards. Additionally, it can be executed early in the CI/CD pipeline or directly from your IDE before committing your changes.

CI/CD is crucial for your code, as stated in CI/CD Best Practices, which says:

A well-executed automated build pipeline will help you and your team consistently deliver working software quickly and get prompt feedback on your latest changes.

It can also be related to the static analysis phase of your project.

Note: keep in mind that static analysis does not include tests. Tests execute the code, which means it is not a static analysis. In this case, it would be considered dynamic analysis. Transpilers also do not fall under static analysis, as they are tools that transform the syntax of your code into a different structure while attempting to maintain logical equivalence.

And, still regarding transpilers, let’s take a look at what The ReadME Project mentions about them:

Transpilers are tools that transform the syntax of your source code into a different structure while maintaining logical equivalence. (…)Though frequently used alongside static analysis tools, they typically do not perform code analysis themselves. Transpilers and type checkers are routinely used together, and the combination of the two is often referred to as a compiler.

But with all that explained, let’s take a look at some examples. Below are two of the tools we’ll cover throughout this blog post—ones you’ve probably already heard of:

Eslint and Prettier

They are used in various projects. You can see below an image that exemplifies what a Pipeline in GitLab usually looks like, for example:

A Pipeline example with many jobs: build-job1, text-job3, deploy-job2, etc

(Image from GitLab Docs )

One of the jobs is a ‘lint-job’, which provides an example of static analysis in one of the steps of the application’s pipeline.

Usually, static analysis aims to identify security vulnerabilities, potential runtime errors, and maintenance requirements.

Additionally, with more comprehensive feedback, it’s possible to detect errors more quickly and accurately, which is incredibly helpful for any developer. In other words, consistent checks and fast, targeted feedback for problem resolution.

Linters x Formatters

There are three main types of static analysis:

  1. Formatters: provide stylistic consistency.
  2. Type checkers: issue warnings about incorrect usage in our code.
  3. Linters: detect logical inconsistencies, in addition to the stylistic issues that formatters address.

Note: I will not focus on type checkers in this blog post, since we will compare linters and formatters in practice.

With these definitions in mind, it is important to understand the negatives of using them. After all, there are also some concerns regarding static analysis:

  • Time consumption: analyzing the entire codebase may take a significant amount of time depending on your project’s size. Even when automated, someone still needs to interpret the results.
  • Possibility of false negatives: some errors might go undetected, which could also waste time.
  • Limited scope: as mentioned briefly before, the analysis is performed without executing the code. Therefore, errors that rely solely on runtime behavior might not be detected.

But, even so, it’s important to use static analysis tools. Because when combined with tests in a complete CI/CD pipeline, for example, your code will be much better protected against potential issues.

It’s not the only solution for code quality or readability, but knowing when and which tools to use for static analysis is incredibly beneficial.

So, shall we check out some tools that let us perform these analyses? 😊

Linters

As mentioned in the Sonar – linter developers guide:

In essence, a linter serves as a valuable developer tool for improving and enhancing code quality. It achieves this by analyzing static source code to identify and flag issues that can lead to bugs, vulnerabilities, and code smells.

Basically, it scans your code. Then, it attempts to find potential errors or outdated patterns that might affect your code, offering suggestions before it goes into production.

In general, a linter follows these steps: it parses the source code, compares it against a set of defined rules, generates an issue report, and provides possible solutions.

Its main benefits include:

  • Higher code quality. 🧹

  • Faster development/productivity. 🚀

A well-known example is: ESLint. Its website’s landing page highlights a few key details:

Eslint landing page

As shown above, ESLint is a linter for JavaScript and TypeScript, offering customizable rules that cover both software quality and style issues.

It’s incredibly useful and a great way to start checking if your JS code needs any improvements!

And ESLint provides a visual example of how its warnings pop up. 👀 Check out the red highlight below:

Eslint features

  • ESLint – Setup

For installation, you’ll need Node.js (^18.18.0, ^20.9.0, or >=21.1.0). Additionally, you can follow this guide, but basically, in most cases, you can just type:

npm init @eslint/config@latest

Then, run it on a specific file like this:

npx eslint yourfile.js

After that, you can define your specific configurations once you better understand how some of these rules work. To help you get a better grip on the rules in action, let’s take a look at a small example. 🚀

There’s a playground where you can test some lines of code and get to know the tool better! Check out the Playground link

Let’s give it a try, write the code with errors below in your playground:

function calculateSum(a, b) {
  let result = a + b
  return result;
}

const unusedVariable = 42;

function sumArray(arr) {
  for (let i = 0; i < arr.length; i++) {
    console.log('Adding:', arr[i]);
  }
}

calculateSum(5, 10)
sumArray([1, 2, 3, 4, 5]);

The playground is super useful because it shows the link to the rule that wasn’t followed, taking us straight to the ESLint documentation. Pretty handy, right? 😎 It already helps us understand our errors better.

Let’s check out our feedback:

Example of feedback lint

It’s clear that this was an extremely simple example. But just imagine having to search through lines and lines of code, spending a lot of time fixing those errors. That’s where tools like ESLint save tons of time for devs!

Formatters

With linters understood, formatters are much easier to grasp: they fix style, spacing, comments — reinforcing formatting rules and can be easily automated.

While linters focus on construction errors, formatters are all about readability and organizing your code. ✨

Besides that, its focus is agility too: the formatters quickly reformat your code to maintain consistency. This allows for better readability.

It’s also important to keep in mind the following, as mentioned in an article from The ReadME Project:

A crucial feature of formatters, which sets them apart from other types of static analysis, is that they do not alter the behavior of your code. They don’t rename, remove, or otherwise mangle constructs declared in code. Formatters are exclusively for formatting.

In summary, just remember that the changes made in your code are not the ones that affect its performance, for example.

Let’s take a look at an example: Prettier:

Prettier landing page

One of the most popular formatters for multiple languages

  • Prettier – Setup
  1. npm install --save-dev --save-exact prettier

  2. echo {} > .prettierrc.json

  3. Create a .prettierignore file

  4. Format all files with Prettier: npx prettier --write src/**/*.js

  5. Recommended: run directly from the editor.

If you use ESLint, install:

eslint-config-prettier

This allows ESLint and Prettier to work together.

Now, let’s practice on the Prettier Playground. Write the following "ugly" code below in it:

function getUserData(id){return fetch(`https://api.example.com/user/${id}`).then(res=>res.json()).then(data=>{console.log('User Data:',data);return data}).catch(err=>{console.error('Error:',err)})}

const items=[1,2,3,4,5];items.forEach(item=>{if(item%2===0){console.log(item,"is even")}else{console.log(item,"is odd")}})

Now, check out the result in the playground. See how much easier it is to read the code? It’s a better experience for devs, and the functionality hasn’t changed at all.

I also recommend installing the VSCode extension: # Prettier – Code formatter. It can be super helpful when you’re starting and helps keep your code nice and tidy. 🖌️

Using these formatters and linters will make your development flow smoother, with fewer problems, as long as you use these tools wisely. So, I recommend testing different pieces of code on the playground to better understand their benefits and figure out which specific rules you should or shouldn’t use in your project or during your studies.

Now that we’ve covered that, let’s also touch on the topic related to git Hooks. Let’s dive in!

Husky🐺: git hook

The focus here is on ensuring a standard. Husky is a git hook. According to MDN Docs:

What is a git hook? Git (not GitHub) provides a system that lets us attach pre- and post-actions to the tasks we perform with git (such as committing your code). Although git hooks can be a bit overly complicated (in this author’s opinion), once they’re in place they can be very powerful. If you’re interested in using hooks, Husky is a greatly simplified route into using hooks.

  • Git hooks are scripts that are automatically triggered at specific points in your code.

Pre-commit hooks: these are executed before you finalize the commit. They check and enforce your code standards, run tests, and handle other tasks to maintain the code quality.

And there’s Husky, a Git Hook manager that simplifies the process of integrating and managing hooks in your project.

Pretty interesting, right?

  • Husky – Setup

Run the following command:

npm install --save-dev husky

If we want to run lint and tests before making a commit, we can add the following to our package.json:

Husky settings

And there are many cool benefits to using Husky 🐺:

  • Ensures code quality

  • Consistency across the team’s codebase 🔧

  • Saves time and resources by addressing important issues early in the development process ⏱️

But when should I use formatters, linters, and git hooks with my team?

When to use them in a team

Let’s talk about some important tips on what to do if you need to set up a linter.

Remember, each project has its context.

For example: don’t just reuse rules from other projects without analyzing the context of your project.

The rules shouldn’t slow down development and can change based on the team’s "feeling".

  • IF IT’S THE BEGINNING OF A PROJECT

Consult the dev team and try to understand if there’s a pattern being followed in similar projects. That’s very important. We want to avoid conflict and future problems.

You can’t get everything right on the first try, so don’t worry about covering all possible cases.

  • IF THE PROJECT IS IN PROGRESS

If there are a huge number of //eslint-disable comments, warnings, etc., it’s the right time to suggest a refactor of the ESLint config and reassess the rules.

But of course, you should understand your project’s needs and how your team is working before making any drastic changes. 🤝

Next steps

After learning how to use all these tools and practicing online, you can apply them to some of your projects or better understand how they work within your team. This way, you’ll be able to work with them all together without any confusion, making the most of their potential.

I also recommend researching more about the ESLint rules. In addition, try applying Husky to small personal projects to get hands-on experience with its setup in the package.json I mentioned.

Happy coding! 🙂

Previously: JavaScript Beginner’s Guide

This post is part of our ‘The Miners’ Guide to Code Crafting’ series, designed to help aspiring developers learn and grow. Stay tuned for more and continue your coding journey with us!! Check out the full summary here!

References

We want to work with you. Check out our "What We Do" section!

Iasmim Cristina

Frontend developer and UX enthusiast. Passionate about expanding my knowledge through projects, tools, and broad perspectives.

View all posts by Iasmim Cristina →