Guide pratique de l'utilisation des Linters
Tags: french, productivity, tooling
Published: 2024-04-24 12:30:54

Nous avons tous déjà vécu un onboarding sur un projet où on fait des copier/coller d’une autre fonctionnalité qui ressemble à ce qu’on veut faire. Nous réadaptons le code, nous commitons et nous pushons. Nous ouvrons la MR/PR et la revue est catastrophique. Le code que nous avons copié-collé est du code legacy, nous avons 15 fois le même commentaire qui nous dit d'utiliser des *const* pour déclarer nos variables, etc. Tout cela nous fait perdre du temps, et ne nous met pas dans les meilleures conditions pour apprécier le projet.

Dans cet article vous allez (re)découvrir comment les linters peuvent vous éviter ces pièges et vous aider à développer.

Avant d’aborder les avantages d’un linter, nous allons expliquer ce que c’est

## Qu’est-ce qu’un linter ?

Techniquement, c’est un outil qui fait de l’analyse statique de votre code donc directement dans votre fichier sans que le code soit build ou soit en train de run. 

Cela permet d’avoir une boucle de feedback très courte 🤩

### Sévérité

Vous allez retrouver en général deux types de sévérité dans un linter qui sont les *Warnings* et les *Errors.*

Les *Warnings* sont des problèmes potentiels qui n'empêchent pas l'exécution du code, mais indiquent des pratiques à améliorer pour maintenir la qualité et la cohérence du code.

Les *Errors* sont des problèmes bloquants qui empêchent le code de fonctionner correctement. Elles doivent être corrigées avant de pouvoir compiler ou exécuter le programme.


> 🧐 Pour information
> Dans la plupart des projets, vous allez retrouver la règle *no-warning* dans notre CI. Ce qui fait que si vous avez une règle en *warning* qui est détecté alors votre CI va planter.
> Personnellement, je n’aime pas cette feature, car elle vous obligent à tout faire d’un coup. Je vous en reparle dans la partie “Mieux refactorer du code legacy”


## Rendre l’implicite explicite

En mettant en place un ou des linters, vous allez pouvoir rendre l’implicite **explicite**, c'est-à-dire faire émerger des règles et des conventions qui peuvent ne pas être documentées ou comprises par tous les membres de l'équipe.

Par exemple, un linter peut vérifier que vos attributs sont dans l’ordre alphabétique, que vos variables sont bien immuables (en JS, n'utiliser que des *const*), que vous respectez les normes sur le nommage de variable, de classes ou de fonctions dans votre projet. Ces règles peuvent sembler mineures, mais elles contribuent à la lisibilité et à la compréhension du code par tous les membres de l'équipe.

En rendant ces règles explicites grâce à un linter, vous pouvez vous assurer que tout le monde suit les mêmes conventions et que le code soit cohérent et facile à comprendre. Cela peut également faciliter l'intégration de nouveaux membres dans l'équipe, car les règles sont clairement définies et documentées.

## Apprendre

En utilisant un linter, vous pouvez apprendre de nouvelles pratiques. Les linters peuvent vous aider à découvrir des règles et des conventions que vous ne connaissiez peut-être pas auparavant, ainsi que les raisons pour lesquelles ces règles sont importantes.

Par exemple, en utilisant un linter pour JavaScript, vous pouvez apprendre que la méthode "reduce" peut être moins performante qu'une boucle "for" dans certaines situations. En comprenant pourquoi cette règle est importante, vous pouvez prendre de meilleures décisions

*([https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-array-reduce.md](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-array-reduce.md))*

De plus, les linters peuvent vous aider à améliorer votre code que ça soit sur la lisibilité, la séparation de la logique, la sécurité ([Snyk](https://snyk.io/fr/), [Sonar](https://www.sonarsource.com/products/sonarqube/) etc) et la performance. En comprenant pourquoi ces règles sont importantes, vous pouvez non seulement écrire du code plus propre et plus efficace, mais également vous améliorer.

## Mieux refactorer du code legacy

Lorsque vous travaillez sur une application existante avec du code legacy, un linter peut être un outil très utile pour vous aider à nettoyer et à mettre à jour votre code. Vous pouvez aussi identifier les parties de votre code qui doivent être mises à jour ou supprimées, et suivre votre progression au fil du temps.

Par exemple, supposons que vous souhaitiez supprimer une bibliothèque (comme Lodash) de votre application. Cependant, le faire d'un coup peut être trop risqué ou trop complexe. Dans ce cas, vous pouvez commencer par ajouter une règle de linter en mode *warning* sur l'utilisation de Lodash. Cela vous permettra de savoir chaque fois que vous utilisez Lodash dans votre code et de commencer à le supprimer progressivement. De plus, l’ajouter en mode *warning* permet aussi à ce qu’un nouveau ou une personne qui rentre de vacances sache qu’il ne doit plus l’utiliser.

En suivant le nombre d'avertissements de cette règle, vous pouvez suivre votre progression. Aussi, vous pouvez être sûr que tout nouveau code que vous écrivez ne dépendra pas de Lodash, ce qui facilitera la suppression complète de la bibliothèque à l'avenir.


> 💡 Je vous conseille fortement de ne pas avoir plus d’une règle en *warning* pour ne pas avoir trop de choses à faire d’un coup

Attention, un linter apporte aussi une certaine complexité, qui peut vous freiner ou être un point de souffrance.

Par exemple, vous avez deux règles qui, individuellement, semblent cohérentes :

- Mets en dernier les paramètres qui ont une valeur par défaut
- Trie les paramètres dans l’ordre alphabétique

Tant que vous n’avez pas les deux en même temps, il n’y a aucun problème. Mais si vous avez ça:

```js
// Mets en dernier les paramètres qui ont une valeur par défaut
function handleThings(value, opts = {}) {
  // ...
}

// Trie les paramètre dans l'ordre alphabétique
function handleThings(opts = {}, value) { 
	 // ...
}
```

Vos règles vont se marcher dessus. Pour éviter cela, je vous conseille donc de faire attention à ces deux points.

## Ajout de règle sans cesse

L'ajout de règles sans limite peut devenir contre-productif et entraver le bon déroulement du projet. Il est important de trouver un équilibre entre la qualité du code et la productivité de l'équipe.
Je vous recommande de ne pas ajouter trop de règles d'un coup, mais plutôt de les introduire progressivement en fonction des besoins du projet et de l'équipe. Il est également utile de régulièrement réévaluer les règles existantes pour s'assurer qu'elles soient toujours pertinentes.


> 💡 Je vous conseille fortement de faire des discussions régulières pour parler des règles de linter, de choisir si vous devez la garder ou rajouter des règles si besoin. Pendant ces discussions il est important de documenter pourquoi vous mettez en place une règle ou pourquoi vous enlevez une règle


Le nombre idéal de règles dépend du projet et de l'équipe. 

La seule question que vous devez vous poser c’est si la règle est **pertinente** dans votre contexte. 

## Configuration complexe

La configuration d'un linter peut devenir compliquée avec le temps et nécessitera une maintenance régulière pour rester efficace. Si la configuration n'est pas bien gérée, cela peut entraîner des problèmes tels que des règles contradictoires ou non pertinentes pour le projet. 

Il est important de prendre le temps de comprendre l'historique de la configuration du linter avant de faire des modifications ou de critiquer la configuration actuelle. Il peut être utile de discuter avec les membres de l'équipe qui ont travaillé précédemment sur la configuration  pour comprendre les raisons derrière certaines décisions. 

En outre, il est important de documenter les changements apportés à la configuration du linter et de communiquer ces changements à l'équipe. Cela peut aider à éviter les conflits et à maintenir une configuration cohérente et efficace. 

### Comment gérer la documentation de son linter ?

Je recommande de stocker la documentation de votre linter à proximité du code, dans le même dépôt git


> ❓ Pourquoi proche du code ?
> Si vous stockez la documentation du linter dans un outil externe tel que Confluence ou un autre référentiel qui génère un site web à partir de fichiers markdown, vous risquez de rencontrer des problèmes de synchronisation. 
> Par exemple, quelqu'un peut oublier de mettre à jour la documentation ou vous n'y avez pas accès pour une raison quelconque. 
> En revanche, si vous stockez la documentation du linter au même endroit que le code, vous réduisez considérablement le risque de désynchronisation. 
> De plus, cela facilite l'accès à la documentation pour les développeurs qui travaillent sur le projet.

Vous pouvez créer un dossier `docs` à la racine de votre projet. Ce dossier va contenir d’autres dossiers.


> 💡 N'oubliez pas d'exclure ce dossier de vos outils de build ou autres.

Par exemple, un dossier `eslint`, qui contiendra un fichier où vous expliquerez pourquoi vous avez utilisé certains plugins eslint et pourquoi vous avez désactivé ou ajouté certaines règles de lint. Bien sûr, n'oubliez pas d'ajouter les dates.

> 💡 Il est important que toutes les modifications de règles renvoient à la documentation de la règle ou du plugin.


Voici un exemple de fichier :


![Exemple de doc sur un projet](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ddfg9rx38uv8now5i7rm.png)



## Quelques linters pour vous lancer

Voici une liste de linters pour vous lancer avec le langage ou le format du fichier :

| Langage | Linter |
| --- | --- |
| JS/TS | [eslint](https://eslint.org/), [Biome](https://biomejs.dev/) |
| Java | [checkstyle](https://checkstyle.sourceforge.io/) |
| Go | [GolangCi-lint](https://golangci-lint.run/) |
| Rust | [Clippy](https://github.com/rust-lang/rust-clippy?tab=readme-ov-file#clippy) |
| Yaml | [Yamllint](https://yamllint.readthedocs.io/en/stable/) |
| OpenApi | [Spectral](https://docs.stoplight.io/docs/spectral/674b27b261c3c-overview) |


> 💡 Si vous recherchez un linter pour votre langage ou un format de fichier, je vous conseille de regarder sur [Megalinter](https://megalinter.io/latest/)


Voilà j’espère vous avoir donné envie d’utiliser un linter ou des pistes pour améliorer votre expérience avec les linters 🐵