TP - Documentation technique de code

1. Présentation

Ce TP s’intéresse à la documentation technique du code source d’un logiciel, afin de le rendre plus facilement compréhensible et réutilisable. En particulier, vous verrez comment définir un README et des commentaires externes détaillés, et comment utiliser un outil pour générer une documentation complète à partir de tout cela.

  • La première partie de ce TP est un ensemble de notions, à savoir les principes de la documentation technique à l’aide notamment de commentaires externes ajoutés dans le code.

  • La seconde partie de ce TP est un travail pratique, où vous ferez un mini projet TypeScript que vous documenterez.

2. Notions sur la documentation technique

2.1. Pourquoi documenter ?

La documentation technique d’un logiciel est un ensemble d’informations expliquant comment son code source fonctionne, et comment il peut être (ré)utilisé pour du développement logiciel. Ce sont donc des informations dédiées à des développeurs. Deux catégories de développeurs sont susceptibles de lire cette documentation :

  • Les développeurs internes du code source documenté (qui sont eux même les auteurs de la documentation) souhaitant mieux comprendre certaines parties de leur propre logiciel, et mieux commuiniquer entre eux,

  • Les développeurs externes, qui n’ont pas développé le code source mais qui souhaitent en ré-utiliser le contenu au sein de leur propre projet logiciel, et qui ont donc pour cela besoin de documentation afin de bien comprendre comment faire usage de ce code.

À retenir : avoir accès à une documentation technique est crucial pour toute personne devant lire, utiliser ou modifier le code source d’un logiciel.

2.2. Quoi et comment documenter ?

Dans une documentation technique, on distinguera la documentation du projet dans son ensemble, et la documentation des différentes parties du code source.

2.2.1. Documenter le projet dans son ensemble

D’abord, la documentation du projet dans son ensemble comprend en règle générale :

  • une description du projet, de son but, des fonctionnalités,

  • des instructions pour configurer, compiler, installer le logiciel (si pertinent),

  • des instructions sur comment utiliser le logiciel,

  • une description de la structure du projet, en terme de répertoires, de fichiers, de code,

  • des informations sur la license logicielle utilisée,

  • des informations de contact.

Pour ce faire, il est d’usage d’écrire un fichier dit README à la racine du projet logiciel. C’est un fichier texte simple pouvant facilement être ouvert dans un éditeur de code, pour être facilement lisible par les développeurs. Souvent, ce fichier suivra la syntaxe d’un format comme Markdown (et sera alors nommé README.md) ou Asciidoc (et sera alors nommé README.adoc, comme le présent document que vous êtes en train de lire !), afin d’être plus lisible et convertible en format HTML.

2.2.2. Documenter les différentes parties du code source

Ensuite, la documentation des différentes parties du code source comprend en règle générale (dans le cas de TypeScript) :

  • La description de chaque module (pour rappel, en TypeScript chaque fichier .ts est un module) : à quoi il sert, ce qu’il contient, ses relations avec d’autres modules.

  • La documentation de chaque fonction présente dans le code du projet, avec :

    • Une description sur ce qu’elle réalise et à quoi elle sert,

    • Une description de chacun de ses paramètres,

    • Une description de sa valeur de retour (quand il y en a une),

    • Optionnellement, des indications sur comment la fonction réalise son but.

  • La documentation de chaque nouveau type de données (enregistrements, enumérations, etc.) présent dans le code du projet, avec :

    • Une description de ce que représente ce type de données,

    • Dans le cas des enregistrements, une description de chaque attribut.

Pour ce faire, une technique répandue est de directement écrire des commentaires externes à l’intérieur même du code source. Comme une documentation technique peut être assez verbeuse, on utilise généralement des blocs de commentaires, aussi appelés commentaires multi-lignes (/* */ en TypeScript). Ainsi, une personne lisant le code source aura directement sous les yeux la documentation technique associée, ce qui lui permettra de plus facilement et rapidement comprendre à quoi sert le code et comment il fonctionne. C’est particulièrement utile pour les développeurs internes.

Pour rappel, on appelle commentaire interne un commentaire présent à l'intérieur d’une fonction, et on appelle commentaire externe un commentaire qui est à l’extérieur d’une fonction.

Attention : cela n’a rien à voir avec la notion de développeur interne ou externe !

2.2.3. Générer une documentation technique externe

Enfin, si les commentaires sont bien écrits et suivent une structure précise et imposée, il est possible d’utiliser un outil automatique capable de lire le README et les commentaires afin de générer automatiquement une documentation lisible en dehors du code source, souvent sous format HTML ouvrable dans un navigateur. Pouvoir parcourir la documentation de manière séparée du code est particulièrement utile pour les développeurs externes.

Voyons maintenant comment faire tout cela concrètement avec l’outil TypeDoc pour TypeScript !

2.3. Écriture et génération de documentation à l’aide de TypeDoc

2.3.1. Présentation de TypeDoc

TypeDoc est un outil communautaire capable de générer une documentation technique externe à partir d’un projet TypeScript bien commenté et configuré. Il produit une jolie documentation en format HTML qu’il est ensuite possible de visionner dans un navigateur web.

documentation schema.drawio

Pour générer une documentation technique structurée, TypeDoc est capable de lire certain nombre d'étiquettes (tags en anglais) au sein des commentaires externes. Elles prennent la forme @etiquette, et permettent soit de donner des informations supplémentaires sur les éléments documentés (ex. @param pour indiquer un paramètre d’une fonction), soit d’influencer la génération de documentation (ex. @ignore pour indiquer que quelque chose ne doit pas être documenté).

Voyons maintenant comment documenter les différentes parties d’un projet TypeScript : le projet dans son ensemble, un module, une fonction, et un enregistrement.

2.3.2. Documenter le projet dans son ensemble

Pour documenter un projet dans son ensemble, il faut créer un fichier appelé README.md, et le remplir avec les informations choisies. Le contenu de ce fichier sera automatiquement utilisé pour remplir la page d’accueil de la documentation technique générée par TypeDoc.

L’extension .md signifie que le fichier suit la syntaxe du langage Markdown. Pour ce cours, ce n’est pas nécessaire de connaître Markdown, et vous pouvez écrire du simple texte dans ce fichier, malgré son extension.

2.3.3. Documenter un module

En TypeScript, on appelle module un fichier contenant du code TypeScript.

Pour documenter un module avec TypeDoc, on écrit un bloc de commentaire au tout début du fichier, et on ajoute l’étiquette @module à la fin de ce bloc.

Exemple 1. Exemple de documentation d’un module
/**
 * Set of functions to build geometric shapes using Points.
 *
 * @module
 */

Le contenu d’un tel commentaire de module sera automatiquement utilisé au début de la page de documentation du dit module, dans la documentation technique générée par TypeDoc.

2.3.4. Documenter une fonction

Pour documenter une fonction avec TypeDoc, on écrit un bloc de commentaire juste avant la fonction, et on utilise les deux étiquettes suivantes :

  • @param permet de décrire un des paramètres de la fonction,

  • @returns permet de décrire ce que rend cette fonction.

Exemple 2. Exemple de documentation d’une fonction
/**
 * Creates a Segment using two Points.
 * @param point1 The first end of the segment.
 * @param point2 The second end of the segments.
 * @returns The segment created from the two points.
 */
function createSegment(point1: Point, point2: Point) : Segment { ... }

2.3.5. Documenter un type de données

Pour documenter un type de données avec TypeDoc (ex. enregistrement ou énumération), on écrit un bloc de commentaire juste avant la déclaration du type.

Dans le cas d’un enregistrement, on écrit également un bloc de commentaire pour chacun de ses attributs.

Aucune étiquette particulière est nécessaire.

Exemple 3. Exemple de documentation d’un type de données
/**
 * Represents a point on an Euclidean plane.
 */
type Point = {

    /**
     * Abscissa.
     */
    x: number,

    /**
     * Ordinate.
     */
    y: number

}

/**
 * Represents the direction of a given element.
 */
enum Direction {
    Up,
    Down,
    Left,
    Right
}

2.3.6. Autres étiquettes utiles

TypeDoc fournit d’autres étiquettes pouvant être utiles, notamment les deux suivantes :

  • @ignore pour indiquer qu’aucune documentation ne doit être généré pour cet élément,

  • @category pour regrouper différents éléments d’un module au sein d’une catégorie.

2.3.7. Configurer un projet et exécuter TypeDoc

Pour pouvoir exécuter TypeDoc sur un projet bien commenté, il faut déclarer TypeDoc comme dépendance, et configurer une nouvelle commande pour appeler TypeDoc. Pour cela, il faut ajouter au projet le fichier package.json suivant (qui ressemble à celui du TP sur le test), en remplaçant mon_projet par le nom que vous souhaitez donner à votre projet :

{
    "name": "mon_projet",
    "scripts": {
        "docs": "typedoc --readme README.md --entryPointStrategy expand src"
    },
    "devDependencies": {
        "typedoc": "0.25.8"
    }
}

Puis, pour installer les dépendances spécifiées dans package.json (et donc TypeDoc), il faut ouvrir un terminal, vous rendre dans le répertoire de votre projet, et exécuter la commande suivante :

$ npm install

Enfin, pour appeler TypeDoc, vous pouvez appeler la commande suivante :

$ npm run docs

Normalement TypeDoc va produire un répertoire docs contenant des fichiers HTML. Vous pouvez ouvrir le fichier docs/index.html dans un navigateur web, et contempler votre documentation technique ! Vous pouvez notamment aller de module en module à l’aide de la barre de navigation tout à droite.

3. Exercice pratique : Jeu de cartes

Dans cette partie, vous allez appliquer ces notions pour coder et documenter un petit projet TypeScript de développement de fonctions pour manipuler un jeu de 52 cartes classique.

3.1. Préparation du projet

  1. Créez un nouveau projet privé sur le Gitlab de l’université, avec le nom que vous souhaitez.

  2. Clonez avec git votre dépôt sur votre ordinateur de travail, ce qui vous donnera un nouveau répertoire.

  3. Ouvrez un terminal, allez dans le répertoire, et préparez le contenu suivant :

    • Un fichier tsconfig.json avec le contenu habituel.

    • Un fichier package.json comme expliqué dans la partie cours présentée plus haut.

    • Un fichier .gitignore contenant la liste de tous les répertoires qui seront générés et donc que l’on ne voudra pas versionner avec git, à savoir :

      node_modules
      docs
      build
  4. Effectuez un commit qui ajoute ces trois fichiers à votre dépôt git, et effectuez un push qui envoie ce commit dans votre dépôt Gitlab distant.

  5. Enfin, ouvrez ce répertoire dans Visual Studio Code. Vous êtes prêt à commencer !

Tout au long de cet exercice, appliquez bien tout ce qui a été vu en TP Gitlab, et pensez à faire des commits et des push régulièrement !

3.2. Implémentation et documentation

Dans votre projet, créez un répertoire src (comme d’habitude), et implémentez et documentez tous les éléments suivants.

  • Un module card, qui permet de créer des cartes et de les manipuler. Ce module doit comprendre :

    • Une enumération Color qui définit les différentes couleurs d’un jeu de carte (pique, carreau, trèfle et cœur),

    • Un enregistrement Card qui permet de représenter des cartes, chacune avec une couleur et une valeur allant de 2 à 14 (note: on peut considérer que le valet vaut 11, la dame 12, le roi 13, et l’as 14).

    • Une fonction createCard pour créer une carte à partir d’un couleur et d’une valeur.

    • Une fonction displayCard qui affiche une carte dans la console (conseil : utiliser les emojis ♣️,♦️,♥️,♠️).

    • Une fonction compareCard qui prend deux cartes et renvoie une valeur positive si la première carte est plus forte, zéro si elles ont les mêmes valeurs, et une valeur négative si la première carte est moins forte.

  • Un module game qui permet de créer et manipuler un jeu de cartes, avec :

    • Une fonction createGame qui renvoie l’ensemble des 52 cartes possibles sous la forme d’un tableau.

    • Une fonction drawCard qui retire la première carte d’un tableau de cartes, et qui la rend en valeur de retour.

N’oubliez pas d’également (brièvement) documenter le projet dans son ensemble avec un README.md ! Voir la partie du cours concernée plus haut.

Il se peut que vous ayez besoin de retirer des éléments à un tableau, ou alors d’insérer des éléments au milieu d’un tableau. Pour cela, il existe en TypeScript une fonction utilitaire appelée splice(<index>, <nb éléments retirés>, <remplacement>) que l’on peut utiliser de la sorte :

let t1: string[] = ["a", "b", "c"]
t1.splice(0, 1) // retire "1" élément à partir de l'index "0" , donc retire "a", donc t1 = ["b", "c"]

let t2: string[] = ["a", "b", "c"]
t2.splice(1, 1) // retire "1" élément à partir de l'index "1" , donc retire "b", donc t2 = ["a", "c"]

let t3: string[] = ["a", "b", "c"]
t3.splice(1, 1, "x") // retire "1" élément à partir de l'index "1" , et ajoute "x" à la place, donc t3 = ["a", "x", "c"]

let t4: string[] = ["a", "b", "c"]
t4.splice(1, 0, "x") // retire "0" élément à partir de l'index "1" , et ajoute "x" à la place, donc t4 = ["a", "x, "b, "c"]

3.3. Génération de documentation HTML avec TypeDoc

Au fur et à mesure que vous implémentez et documentez votre code, générez la documentation HTML à l’aide de TypeDoc. Voir la partie du cours concernée plus haut.

Dernier conseil :

Retenez que le but de cet exercice est d’apprendre à écrire une documentation technique !

  • Ce n’est pas grave si le code à l’intérieur de vos fonctions n’est pas parfait !

  • Prenez avant tout bien le temps de configurer votre projet pour générer la documentation avec TypeDoc, d’écrire un bref README, et de bien écrire des commentaires externes pour tous les éléments pertinents de votre code, comme expliqué dans la partie cours.