Outils de Développement de Logiciels: Une Vue d'Ensemble
- 17 juin 2024
- 13 mins de lecture
- Concepts de programmation
Table des matières
Lorsque j’apprends un langage de programmation, l’une des premières choses que j’essaie de comprendre est comment transformer le code écrit en un artefact déployable (installable) et exécutable. Je commence par déterminer le type de langage de programmation, spécifiquement s’il nécessite une étape de compilation et si un interpréteur est requis à l’exécution. Ensuite, je me penche sur les outils de programmation ou la chaîne d’outils nécessaires pour faire le build et empaqueter toute application que je développe.
Cet article traite des différents types d’outils nécessaires pour gérer le build et l’empaquetage de logiciels. Tout d’abord, nous expliquons les méthodes courantes pour configurer la chaîne d’outils. Ensuite, nous décrivons les outils de la chaîne d’outils.
​
Préparer la Chaîne d’Outils
Avant de faire le build du code, vous devez disposer des outils de programmation nécessaires. Vous pouvez y parvenir de l’une des manières suivantes :
- Installation manuelle: Les installer à l’aide du gestionnaire de paquets du système ou à partir des sources.
- Installation automatisée: Utiliser un outil de gestion de la chaîne d’outils ou un script d’installation pour une installation automatisée, si disponible.
- Conteneurs de développement: Utiliser un conteneur d’environnement virtuel pré-construit (par exemple, Docker), appelé conteneur de développement, basé sur une image, si disponible.
Pour les langages de programmation qui nécessitent un interpréteur, celui-ci sera également mis à disposition de cette manière, à la fois pour l’étape de construction et pour le temps d’exécution.
Vous pouvez généralement utiliser toute la chaîne d’outils à travers l’Environnement de Développement Intégré (IDE) du langage de programmation ou un pipeline d’Intégration Continue (CI).
Bulletin d'information
Abonnez-vous à notre bulletin d'information et restez informé(e).
​
Composants de la Chaîne d’Outils
Examinons les différents types d’outils et la manière dont ils sont généralement organisés au sein d’un pipeline de développement de logiciels.
​
Outils Primaires
Cette catégorie d’outils traite directement le code. Ils sont utilisés pour vérifier le code source, générer la documentation du code, générer automatiquement du code source à partir du Langage de Description d’Interface (IDL) et des langages de macro, compiler le code (si nécessaire), tester le code, empaqueter le logiciel et le télécharger dans le dépôt de packages (si nécessaire).
​
1. Édition de Code
De nombreux outils peuvent aider les développeurs à écrire du code plus efficacement. Il s’agit notamment d’outils d’autocomplétion, de navigation (dans et entre les fichiers sources) et de mise en évidence de la syntaxe. Ces outils utilisent une analyse légère et sont souvent intégrés dans des éditeurs de texte conçus pour des langages de programmation spécifiques.
De nombreux éditeurs de code modernes utilisent le “Language Server Protocol” (LSP) pour interagir avec ces outils de productivité pour l’écriture de code. Ils l’utilisent également pour interagir avec les outils d’analyse de conformité de code source.
​
2. Analyse de Conformité des Sources
Les outils d’analyse de la conformité des sources sont principalement utilisés pour:
-
Vérifier que les artefacts sources respectent les meilleures pratiques et sont exempts d’erreurs triviales. Ces outils spécifiques sont généralement appelés linters.
-
S’assurer que les artefacts sources respectent les normes de formatage du projet. Ces outils spécifiques sont généralement appelés formateurs.
Certains outils de conformité des sources remplissent à la fois les fonctions de linters et de formateurs.
Note
​
Linter
Les linters analysent le code source, effectuent diverses vérifications et signalent les problèmes aux développeurs pour qu’ils les corrigent. La détection précoce des erreurs permet d’éviter les problèmes lors de la compilation (le cas échéant), des tests ou de l’exécution, améliorant ainsi le cycle de vie du développement logiciel (SDLC). Voici quelques types de contrôles couramment effectués par les linters:
-
Vérifications de l’exactitude de la syntaxe: S’assurer qu’il n’y a pas d’erreurs de syntaxe dans l’artefact source. Ceci est particulièrement utile pour les langages de programmation qui n’ont pas d’étape de compilation au moment du build. C’est également essentiel pour les fichiers de configuration.
-
Vérifications de conformité aux conventions: Vérifier le respect des lignes directrices du projet concernant le style de codage, le nommage des variables, les exigences en matière de commentaires, la complexité du code, la syntaxe préférée, les code smells, etc. Elles jouent un rôle crucial dans le maintien de la cohérence au sein d’un projet et rendent le logiciel plus facile à maintenir. Les exigences de convention n’affectent pas la sémantique mais seulement la syntaxe, et potentiellement les performances du programme.
-
Contrôles des erreurs sémantiques courantes et de sécurité: Il s’agit de vérifier les erreurs sémantiques potentielles et les vulnérabilités telles que les variables non initialisées, les fuites de mémoire, les déréférences de pointeurs nuls, etc.
Certains linters peuvent fournir des correctifs générés automatiquement pour les problèmes qu’ils détectent.
​
Formateur
Les formateurs transforment automatiquement les artefacts source pour qu’ils respectent les directives de style du projet. Les exigences de style mises en œuvre par les formateurs comprennent : la taille et le type d’indentation (tabulations ou espaces), les sauts de ligne, la longueur maximale des lignes de code, l’utilisation d’accolades et leur placement (si pris en charge), l’espacement avant les parenthèses (si pris en charge), et plus encore.
Les formateurs vérifient le style des sources et les transforment pour qu’elles suivent les directives de style. Cette transformation n’affecte pas la sémantique du code.
Tip
Étant donné que les formateurs modifient automatiquement le code sans affecter la sémantique, il est plus naturel d’utiliser les linters avant les formateurs.
​
3. Génération Automatisée de Documentation
Particulièrement utiles pour la documentation des interfaces de programmation d’applications (API), les outils de génération automatisée de documentation créent une documentation visuellement attrayante en extrayant la documentation des artefacts sources. La documentation extraite est souvent rendue au format HTML ou d’autres formats de documentation tels que reStructuredText ou Markdown.
Les outils de documentation des sources sont souvent spécifiques à un langage, ce qui signifie qu’ils prennent généralement en charge un ou quelques langages de programmation ou langages dédié (DSL).
Ces outils utilisent également des fichiers de documentation dédiés pour générer la documentation du projet. En fait, certains outils de génération de documentation n’utilisent que des fichiers de documentation dédiés (tels que reStructuredText ou Markdown) pour générer une page web de documentation. Ce type d’outil de génération de documentation doit être utilisé après avoir généré les fichiers de documentation à partir des artefacts sources à l’aide d’outils de génération de documentation spécifiques à un langage. Mkdocs est un exemple de ce type d’outil.
Les outils de génération de documentation sont configurables, ce qui permet à un fichier de configuration de définir la manière dont la documentation doit être générée. Voici quelques exemples d’options de configuration:
- Code source ou fichiers de documentation dédiés à exclure lors de la génération.
- Format final de la documentation.
- Style et thème à utiliser pour la documentation HTML.
​
4. Génération Automatisée de Code Source
Il existe des scénarios dans le génie logiciel où le code source est généré automatiquement et utilisé pour le build ou l’exécution d’un programme. Les scénarios les plus courants impliquent l’utilisation de macros et de langages de description d’interface (IDL).
Un exemple d’utilisation de macros est un outil système avec un composant qui effectue des appels système qui varient selon les différentes plateformes. Un processeur de macros tel que M4 peut générer les appels corrects au moment du build en fonction de la plateforme sélectionnée. Dans ce cas, les divers appels spécifiques à la plateforme sont développés en utilisant des macros.
Un exemple d’utilisation des IDL est celui d’un microservice qui accède à un serveur via gRPC, où les services du serveur sont définis en utilisant l’IDL Protocol Buffers. Le code du microservice accède aux services du serveur via le code de stub généré à partir des fichiers Protocol Buffers.
​
5. Compilation (si nécessaire)
Certains langages de programmation exigent que le code source soit compilé en code machine ou en code interprété avant d’être exécuté. C’est le cas des langages natifs tels que C, C++, Rust, Go, ainsi que certains langages interprétés tels que Java et Typescript. Le processus de compilation implique plusieurs outils, en fonction de la sortie cible :
-
Compilation en code machine: Le compilateur transforme les fichiers de code source en code assembleur. L’assembleur convertit ensuite le code assembleur en code machine. Pour une bibliothèque, l’archiveur regroupe les fichiers de code machine en une seule archive. Pour un exécutable autonome, l’éditeur de liens combine les fichiers de code machine en un seul, résolvant les références et liant les éléments externes.
-
Compilation en code interprété: Le compilateur convertit les fichiers de code source en code interprété. L’archiveur regroupe ensuite ces fichiers de code interprété en une seule archive.
Pour les langages de programmation qui ne nécessitent pas de compilation, les fichiers de code source eux-mêmes sont exécutables.
​
6. Tests
Il est important de vérifier qu’un programme fonctionne comme prévu, c’est-à-dire qu’il produit les sorties correctes pour des entrées données. Prenons l’exemple d’un programme qui:
- Lit un nombre entier à partir de l’entrée standard.
- Affiche “Est premier” si le nombre est premier ; sinon, affiche “N’est pas premier”.
Si nous exécutons le programme avec l’entrée 3
et qu’il affiche “N’est pas premier”, nous savons qu’il y a une erreur à corriger.
Les outils de test aident à automatiser ce processus en nous permettant de spécifier facilement les entrées et les sorties attendues, d’exécuter le programme et de signaler toute anomalie. Si la sortie du programme ne correspond pas au résultat attendu, cela indique qu’il y a un bug qui doit être corrigé.
Après avoir identifié les erreurs à l’aide des outils de test, il peut être nécessaire de modifier le programme pour les corriger, et le processus de développement revient à la phase d’édition du code.
​
7. Empaquetage des Artéfacts
Lorsque nous sommes satisfaits du code executable obtenu, nous pouvons l’empaqueter pour faciliter son déploiement ou le rendre disponible dans un dépôt de packages.
Note
Les sources DSL peuvent être utilisées directement au moment de l’exécution sans génération de code source. Dans ce cas, les sources DSL doivent être empaquetées avec le code exécutable. Un exemple est le framework d’interface utilisateur graphique (GUI) GTK builder, où les modèles GUI d’un programme sont définis dans des fichiers XML appelé fichiers glade. Ces fichiers glade sont chargés comme ressources du programme au moment de l’exécution.
Les packages peuvent être créés sous la forme native du gestionnaire de packages du langage de programmation ou sous forme d’images de conteneurs du programme, telles que celles créées avec Docker. Ces dernières sont très courantes dans le cadre de l’architecture microservices.
En ce qui concerne les images Docker, l’outil Docker CLI peut être utilisé pour créer des images en utilisant la commande docker build ...
.
Tip
Les packages système peuvent être créés en utilisant l’outil CPack. Cependant, lorsque cela est possible, il est préférable d’utiliser des gestionnaires de packages non système pour gérer facilement les versions, surtout lorsque divers programmes exécutés sur le même système nécessitent différentes versions d’une même bibliothèque.
​
8. Téléchargement des Packages
Une fois les paquets créés, ils doivent souvent être téléchargés dans un dépôt de paquets public ou privé. Ces référentiels fournissent des outils, appelés “publieur de paquets”, pour télécharger les packages.
Par exemple, avec les images Docker, l’outil CLI de Docker peut être utilisé pour publier des images en utilisant la commande docker push ...
.
​
Outils Intermédiaires
La catégorie “outils intermédiaires” comprend les outils qui ne sont pas directement liés à l’édition et au build du code. Il s’agit notamment d’outils de gestion des dépendances, d’orchestration du build et de systèmes de gestion du code source (contrôle de version).
​
1. Gestion des Dépendances
Les ingénieurs logiciels utilisent souvent des programmes existants, appelés dépendances, pour éviter de “réinventer la roue”. Il est essentiel de garder une trace des dépendances utilisées par un projet et leurs versions. Il est également important de les rendre disponibles rapidement et automatiquement.
Cette tâche de gestion des dépendances est souvent prise en charge par des outils appelés gestionnaires de paquets ou gestionnaires de dépendances. Les gestionnaires de paquets modernes utilisent des fichiers de configuration, souvent stockés dans le référentiel du projet, pour s’assurer que les dépendances sont disponibles lors du build.
Note
Bien que les gestionnaires de paquets soient utilisés pour rendre les dépendances disponibles lors du build, ils peuvent également rendre les dépendances d’exécution disponibles au moment de l’exécution.
​
2. Orchestration du Build
Le processus de build implique plusieurs étapes et outils. Pour simplifier et automatiser ce processus, un orchestrateur de build ou outil de build est utilisé. Cet outil est contrôlé par des fichiers de configuration qui décrivent, de manière déclarative ou impérative, les étapes du processus de build.
Note
Un outil de build peut également remplir la fonction de gestionnaire de paquets.
​
3. Gestionnaires de Code Source
L’utilisation de gestionnaires de code source, également appelés outils de contrôle de version, tels que git, est essentielle pour gérer les dépôts de code source des logiciels. Les outils de gestion de code source permettent aux développeurs de:
- Stocker le code source de leurs logiciels dans des référentiels distants
- Conserver un historique des versions du logiciel et passer de l’une à l’autre.
- Développer différentes fonctionnalités du logiciel en parallèle et les fusionner une fois terminées.
- Et bien d’autres choses encore.
Note
Les fichiers de code source ne sont pas les seuls fichiers suivis par les outils de contrôle de version. Les fichiers source de DSL, les fichiers de configuration de build, les fichiers de documentation dédiés et bien d’autres encore sont également suivis.
Bulletin d'information
Abonnez-vous à notre bulletin d'information et restez informé(e).
​
Ce qu’il Faut Rechercher dans un Dépôt de Code
Un dépôt de code source contient souvent les éléments suivants:
- Fichiers de code source développés
- Fichiers source de DSL
- Fichiers de code et de données de test
- Fichiers de documentation dédiés
- (Optionnel) Fichiers de configuration de l’exécution du logiciel
- Fichiers de configuration du gestionnaire de code source (par exemple,
.gitignore
pour Git) - Fichiers de configuration de l’outil d’orchestration de build (par exemple,
Makefile
) - Fichiers de configuration du gestionnaire de paquets
- Fichiers de configuration de l’éditeur de texte
- Fichiers de configuration du linter
- Fichiers de configuration du formateur de code
- Fichiers de configuration de l’outil de test
- Fichiers de configuration du générateur de documentation
- Fichiers de configuration du générateur de code basé sur les DSL
- Fichiers de configuration de l’infrastructure du compilateur
- Fichiers de configuration du générateur et du publieur de paquets