Aller au contenu

Blog ·

De la documentation écrite avant la fusion

Deux phrases d’une nouvelle page de documentation étaient fausses dès sa mise en ligne : une autre branche avait fusionné avant. Ce qu’une garde attrape.

Par Provibr

Une page de documentation est un ensemble d’affirmations sur du code. Cela paraît évident jusqu’à ce que l’on remarque que rien dans la construction ne les vérifie. Les tests affirment des choses sur le code. Les contrôles de types affirment des choses sur le code. La prose sur le code affirme des choses sur le code et se trouve vérifiée par une personne qui la lit une fois, le jour où elle a été écrite.

Nous avons écrit deux nouvelles pages de documentation dans une même ronde : une pour l’éditeur d’automatisations, environ 2930 mots anglais répartis en huit sections, et une pour le tableau de bord, environ 909. Plus une section ajoutée à deux pages qui existaient déjà. Deux phrases de la page d’automatisation étaient déjà fausses au moment de sa mise en ligne.

Personne n’avait écrit de contrevérité. Les deux phrases étaient exactes par rapport à la branche sur laquelle elles avaient été écrites.

La phrase qui était vraie quand elle a été écrite

La documentation d’une fonctionnalité s’écrit d’ordinaire après la fonctionnalité, ce qui veut dire qu’elle s’écrit pendant que d’autres branches sont encore ouvertes. La nôtre l’a été. La page décrivait un nœud de notification et disait, en substance, qu’il n’envoie pas de courriel. Sur la branche contre laquelle elle a été écrite, c’était exactement juste : le nœud écrivait une notification dans le panneau et rien ne sortait de la maison.

Une ronde parallèle a fusionné en premier et a donné au nœud une case à cocher pour le courriel, décochée par défaut, une catégorie de désabonnement qui lui est propre, et une règle selon laquelle une exécution de test n’envoie jamais rien. Chacun de ces faits intéresse un lecteur. Aucun d’eux n’était sur la page, et ce qui s’y trouvait leur disait désormais le contraire.

La deuxième phrase décrivait comment une offre se relie à un flux. Elle disait que l’offre exécute le flux qui se trouve derrière elle, d’une époque où cette relation était de un à un. La même fusion l’a remplacée par une jointure : une offre peut accrocher au plus un flux par moment, sur trois moments, et un flux déclenché manuellement ou par webhook ne peut pas y être accroché du tout. « Ne peut pas être attaché » est une meilleure réponse que « attaché et sans effet en silence », mais c’est une autre réponse, et la page donnait encore l’ancienne.

La réparation était petite. La partie intéressante est la façon dont elle a été trouvée : quelqu’un est allé chercher exprès, car une ronde qui touche à un sujet est le seul moment où quelqu’un a une raison de relire la prose sur ce sujet.

Ce qu’une garde peut attraper

Il existe un second mode de défaillance sur les mêmes pages et, contrairement au premier, il est mécanisable.

La page du tableau de bord contient un tableau listant les cartes qu’un utilisateur peut ajouter. Ces cartes ont des noms, dans neuf langues, et ces noms existent déjà : ce sont les libellés du sélecteur sur lequel l’utilisateur clique vraiment. Écrire un tableau de documentation revient à les écrire une deuxième fois.

Cela a mal tourné tout de suite, dès le premier jet, en anglais :

Dans le sélecteurSur la page de documentation
Integration listConnections
Open ticketsTickets
Credit balanceCredit

Aucun de ces termes n’est faux en tant qu’anglais. Tous les trois sont faux en tant que documentation, car un lecteur à qui l’on dit d’ajouter « Connections » cherchera une carte nommée Connections et trouvera une carte nommée Integration list. La dérive est silencieuse par construction : les deux textes vont très bien chacun de leur côté, et personne ne pose un manuel à côté d’un sélecteur.

Le tableau prend donc désormais les mêmes clés de catalogue que le sélecteur, et un test exige qu’elles soient identiques mot pour mot dans les neuf langues. La clé de documentation est dérivée de l’identifiant de la carte plutôt que listée à la main, pour que la septième carte facultative que quelqu’un ajoutera l’an prochain soit mesurée sans que personne ait à penser à l’ajouter ici. C’est la même forme que la garde que nous faisons tourner entre les deux copies des messages serveur anglais, et elle existe pour la même raison : deux endroits qui détiennent une seule vérité ont besoin d’un test qui le dise, pas d’une convention.

Les noms de boutons de la même page avaient été devinés dans cinq des neuf langues. Ils sortent désormais du catalogue eux aussi. Et trois langues avaient traduit le mot Scripts, qui est le nom d’un élément de menu non traduit dans le produit : la page disait donc à un lecteur espagnol, portugais et ukrainien de cliquer sur quelque chose qui n’existe pas sous ce nom.

Un jeton technique n’est pas un mot

Les noms de produits, les ports, les chemins, les noms de modules et les codes de statut vont dans un jeton à chasse fixe et restent en anglais, où qu’ils apparaissent, dans chaque langue. Cette règle n’est pas nouvelle. Ce qui était nouveau, c’est qu’en l’inscrivant dans ces pages elle est entrée en collision avec deux autres gardes à la fois.

Mettre littéralement un élément <code> dans un tableau de lignes fait trébucher la règle de lint qui veut une clé sur chaque élément JSX d’un tableau, même ici, où le composant de tableau enveloppe chaque cellule dans son propre élément à clé et où la clé n’est jamais lue. Mettre une clé dessus fait trébucher une autre garde, qui voit un enfant à clé posé à côté d’appels de traduction dont elle ne peut pas résoudre les clés dans ce fichier.

L’issue a été une fonction d’une ligne qui renvoie l’élément. Pour la règle de lint, c’est un appel de fonction et non un élément de tableau ; pour l’autre garde, ce n’est pas une clé. Le rendu produit est identique octet pour octet. C’est une petite chose, et c’est le genre de petite chose que l’on règle avec un commentaire de désactivation quand personne n’écrit pourquoi les deux règles étaient en désaccord.

Des captures d’écran qui avaient l’air réussies

La mesure de ces pages comprenait des captures d’écran par ancre : défiler jusqu’à chaque section, la photographier, la regarder.

Neuf d’entre elles montraient l’en-tête de la page.

La commande de navigateur qui capture une région au-delà de la fenêtre calcule son cadrage depuis le haut du document, et non depuis la position de défilement courante. Défilez jusqu’à une ancre située huit écrans plus bas, demandez une région aux coordonnées que l’élément annonce, et vous photographiez le haut de la page à la place, exactement à la bonne taille, dans un fichier au bon nom. Chacune de ces captures était une image plausible de la mauvaise chose.

Ajouter le décalage de défilement courant a réglé le problème. La forme générale est celle que nous rencontrons sans cesse : une mesure qui échoue en produisant une sortie d’apparence normale est pire qu’une mesure qui plante, car le plantage est examiné le jour même.

La part qu’aucune garde n’atteint

Les noms de cartes étaient mécanisables parce que les deux côtés sont des chaînes dans un seul dépôt. Les deux phrases périmées ne l’étaient pas, et il vaut la peine d’être précis sur le pourquoi, car il est tentant de croire que tout problème de documentation a un test qui n’attend que d’être écrit.

Une phrase disant qu’un nœud n’envoie pas de courriel est une affirmation sur un comportement réparti sur quatre fichiers, une valeur par défaut, une case à cocher et une liste de catégories. Il n’existe aucune expression à laquelle la comparer. Le seul mécanisme qui l’attraperait est un test qui produit le comportement et lit la phrase, c’est-à-dire un test à écrire phrase par phrase, par quelqu’un qui sait déjà que la phrase est fausse.

Ce que nous avons fait à la place était moins coûteux et mérite d’être nommé comme une pratique : au moment de la correction, tout le sous-arbre de documentation a été fouillé à la recherche de toute autre affirmation sur le courriel et de toute autre affirmation sur un flux par offre. Il n’y avait pas de troisième endroit. C’est un résultat, pas une formalité. Sans cela, la ronde aurait corrigé deux phrases et laissé au lecteur la croyance raisonnable que la page avait été vérifiée.

La même discipline existe déjà ailleurs dans ce projet pour un autre couple : nos articles de fond peuvent se périmer par rapport à la liste des intégrations en production, et rien ne passe au rouge quand cela arrive. Deux articles ont un jour passé six semaines à dire que deux hyperviseurs étaient sur la feuille de route alors que les deux étaient livrés. La règle qui en est sortie est la même : si une ronde change le statut d’une chose, cherchez son nom dans la prose.

Ce que nous noterions

  1. La prose sur le code est une affirmation non testée. Rien dans la construction ne la lit. Cela va très bien, tant que tout le monde le sait et que personne ne suppose qu’une exécution verte dise quoi que ce soit sur le paragraphe.
  2. La documentation s’écrit contre une branche, pas contre la principale. Si d’autres rondes sont ouvertes, la page est un instantané d’un état qui ne sortira peut-être jamais. Relisez-la après la fusion, pas avant.
  3. Un nom qui existe dans le produit doit être lu, pas retapé. Trois noms de cartes sur six ont dérivé dès le premier jet. En neuf langues, c’est une classe d’erreurs, pas un accident.
  4. Dérivez la clé de documentation de l’identifiant. La carte suivante est alors couverte sans que personne ait à se souvenir de cette règle.
  5. Un mot deviné dans une langue que vous ne lisez pas est invisible. Cinq langues avaient des noms de boutons devinés et rien n’était rouge.
  6. Traduire un nom de produit est une instruction cassée. Si le menu dit Scripts dans chaque langue, le manuel dit Scripts dans chaque langue.
  7. Quand deux règles de lint se contredisent, notez laquelle vous avez suivie et pourquoi. L’alternative est un commentaire de désactivation que personne ne pourra évaluer plus tard.
  8. Une mesure qui produit une sortie plausible quand elle échoue ne sera pas remise en question. Photographiez quelque chose que vous pouvez reconnaître, et regardez les images.

Pour être clair : les deux pages sont en production dans neuf langues, les deux phrases périmées ont été corrigées dans les neuf, et la garde sur les noms de cartes est dans la suite et a été prouvée rouge avant d’être prouvée verte. Les affirmations des pages viennent de la lecture du code et non de son exécution ; l’exemple curl de la page d’automatisation n’a pas été tiré sur un point d’accès en production ; et chaque traduction a eu un lecteur, pas deux.

Issu du travail de plateforme sur Provibr. Les cartes auxquelles ces noms renvoient sont dans un raccourci est une référence, pas un droit, et ce que coûte l’honnêteté de neuf catalogues est dans seize mille clés et neuf langues.

Commencez avec un hôte et un agent

Créez un compte, installez l’agent avec une seule commande et connectez votre premier hôte Proxmox. La période d’essai dure 14 jours et ne demande aucune coordonnée de paiement.