Post en cours de rédaction.
Écrire du code de bonne qualité est indispensable lorsqu'on souhaite développer des applications pérennes qui dépassent un certain niveau de complexité. Pour autant le concept de qualité d'une base de code est difficile à cerner. Il regroupe une multitude d'aspects, et bien souvent deux personnes qui s'y réfèrent ont à l'esprit des choses très différentes. Ici, on explicite une partie de ce qui se cache derrière ce concept de qualité, ainsi que quelques bonnes pratiques de code (en particulier pour le langage Python). Ces bonnes pratiques sont parfois plus faciles à appliquer grâce à un outillage adapté : cet article contient ainsi des liens vers des ressources extérieures permettant d'apprendre à utiliser cet outillage, mais également d'approfondir certains sujets.
Les bases de codes gagnent rapidement en complexité au cours du temps, en particulier quand elles sont le fruit d'un travail collaboratif entre plusieurs contributeurs. Plus la complexité est importante, moins il est rapide de comprendre les implications d'une addition, d'une délétion ou d'une modification d'une partie du code. Si la complexité est trop grande, les erreurs d'implémentation se font beaucoup plus fréquentes. En outre, il est plus difficile pour de nouveaux contributeurs de se joindre au projet, car le coût d'entrée devient très important.
On peut d'une certaine manière voir la qualité comme le fait de limiter la complexité de sa base de code, qui doit rester simple à lire et à comprendre, et à laquelle il doit être facile de contribuer. Sous cet angle, un code est de meilleure qualité qu'un autre s'il conduit au même résultat avec une complexité moindre. Bien entendu il n'existe pas de métrique unique pour mesurer la complexité du code et cette dernière est parfois subjective. Toutefois, il existe des concepts et des principes qui une fois suivis aident à produire du code qui sera en général moins complexe, et donc de meilleure qualité. Dans la suite de cet article, on détaille comment une bonne utilisation de Git, d'outils d'analyse de code statique et de tests unitaires permet de maintenir un niveau de qualité élevé (en abordant quelques points majeurs - on donne aussi des références pour aller plus loin). Ceci est particulièrement important dans un environnement de développement logiciel, mais devient en réalité utile rapidement, dès lors que plusieurs personnes travaillent sur du code commun. En outre, dans un environnement de recherche, respecter les bonnes pratiques dans le cadre de projets expérimentaux permet de minimiser le coût de développement d'une application production-ready en aval.
Tout à un coût et on ne déroge pas à la règle ici. Pour chaque projet, des arbitrages sont nécessaires, car demander un niveau de qualité élevé et donc le respect d'un certain nombre de bonnes pratiques a un prix qu'il n'est pas toujours souhaitable de payer. Il faut toutefois noter que l'apprentissage de bonnes pratiques et de l'utilisation d'outils constitue pour une organisation un investissement qui dépasse le cadre d'un simple projet, et qui apporte des bénéfices sur le long terme.
À noter que les environnements de développement (IDE) intègrent en général des outils d'analyse de code qui surlignent les violations aux conventions de la PEP 8. Il est plus facile d'écrire du code propre stylistiquement en utilisant ces outils (ou des librairies adaptées, voir ci-dessous).
Git est un outil indispensable pour travailler en collaboration sur du code, dont l'utilité augmente avec l'expérience de chaque contributeur. Plusieurs bonnes pratiques sont à souligner concernant l'utilisation de Git, même si de nombreux workflows différents existent :
L'analyse de code statique permet de respecter facilement un grand nombre de bonnes pratiques (en particulier concernant le formatage du code). Même si le code n'est jamais exécuté pendant l'analyse, cette dernière évite de fait beaucoup de bugs qui auraient provoqué des erreurs au runtime. Elle peut se faire dans l'environnement de développement du codeur, mais également dans une pipeline d'intégration et de distribution continue (CI/CD), ce qui est facilement configurable avec Gitlab pour n'intégrer que du code avec un haut niveau de qualité à la branche principale du projet (voir cette page de documentation). Plusieurs outils/standards sont couramment utilisés :
Dans l'environnement de développement du codeur, tous ces outils sont faciles à utiliser au travers de pre-commit hooks. Un pre-commit hook fait tourner un ensemble pré-configuré de contrôles et/ou de formateurs automatiques avant d'effectuer un commit avec Git. Quelques points sur l'utilisation de la librairie :
pre-commit run --files
;git commit -n
, ou même des tests spécifiques ;.pre-commit-config.yaml
à placer à la racine du projet.Cette vidéo montre un exemple de configuration de GitLab pour utiliser les librairies mentionnées ci-dessus dans une pipeline CI/CD.
Les tests unitaires sont un élément très important d'une base de code stable. Un test unitaire aide à vérifier le bon fonctionnement d'une partie précise d'une application (par exemple d'une fonction). En outre, les tests unitaires permettent parfois d'étoffer la documentation de la partie concernée, en montrant comment elle doit être utilisée. Avoir une batterie de tests complète constitue une protection contre l'apparition de bugs lorsqu'une partie du code est modifiée. Avec GitLab, il est possible de configurer la pipeline CI/CD pour qu'un ajout à la branche principale nécessite que tous les tests s'exécutent sans erreur.
La manière optimale de maintenir cette batterie complète pour un dépôt de code est d'implémenter des tests unitaires pertinents en même temps que chaque nouvelle fonctionnalité. La bonne implémentation des tests peut être contrôlée au cours de la revue de code précédant l'intégration à la branche principale.
Pour Python, les frameworks majoritairement utilisés sont :
Les informations qui y sont diffusées n'engagent que les contributeurs et en aucun cas les institutions dont ils dépendent.