24 points par xguru 2020-12-28 | 3 commentaires | Partager sur WhatsApp

Guide open source modernisé tout en respectant les principes Unix traditionnels

  • Philosophie de conception des CLI

 → Priorité à l’humain

 → Des composants simples qui fonctionnent ensemble

 → Maintenir la cohérence entre les programmes

 → Ne dire que le nécessaire (une sortie ni trop faible ni trop verbeuse)

 → Faciliter la découverte (aide complète, exemples, suggestion de la prochaine commande à exécuter, suggestion d’action en cas d’erreur)

 → Comme une conversation ordinaire

 → Être robuste

 → Faire preuve d’empathie envers l’utilisateur

 → Chaos : si vous devez enfreindre les règles, explicitez clairement l’intention et l’objectif

  • Lignes directrices pour les CLI

 → Bases

  ✓ Utiliser une bibliothèque d’analyse de ligne de commande : Go(Cobra,cli), Node(oclif), Python (Click,Typer), Ruby(TTY)

  ✓ Retourner 0 en cas de succès, et un code différent de 0 en cas d’erreur

  ✓ Envoyer la sortie sur stdout

  ✓ Envoyer les messages tels que logs et erreurs sur stderr

 → Aide

  ✓ Si exécuté sans option, afficher l’aide (-h, --help)

  ✓ Afficher par défaut une aide concise

    · Ce que fait ce programme

    · Un ou deux exemples d’appel

    · Explication des flags (s’ils ne sont pas nombreux)

    · --help pour des explications supplémentaires

  ✓ Avec l’option -h, --help, afficher l’aide complète

  ✓ Fournir un canal pour recevoir retours et signalements de problèmes

  ✓ Dans l’aide, fournir un lien vers une documentation web

  ✓ Expliquer à l’aide d’exemples

  ✓ S’il y a beaucoup d’exemples, les publier ailleurs (antisèche ou page web)

  ✓ Ne pas trop se soucier des pages man (elles sont peu utilisées et ne fonctionnent pas sous Windows)

  ✓ Si l’aide est longue, la passer à un pager

  ✓ Afficher au début de l’aide les flags et commandes les plus utilisés

  ✓ Utiliser du formatage dans l’aide (gras)

  ✓ Si l’utilisateur a probablement fait quelque chose de travers et que vous pouvez le deviner, suggérez une correction

  ✓ Si votre commande attend des données via un pipe mais que stdin est un terminal interactif, afficher l’aide et quitter immédiatement

 → Sortie

  ✓ La sortie lisible par un humain est la priorité

  ✓ Fournir une sortie lisible par machine si cela ne nuit pas à l’utilisabilité

  ✓ Si le format lisible par un humain empêche une sortie lisible par machine, proposer une option --plain pour permettre l’usage avec grep / awk, etc.

  ✓ Si --json est fourni, sortir au format JSON

  ✓ En cas de succès, idéalement ne rien afficher, mais si une sortie est nécessaire, rester concis. Prendre en charge -q pour supprimer la sortie non essentielle

  ✓ Si l’état change, le signaler à l’utilisateur (voir la sortie de git push)

  ✓ Faciliter la lecture de l’état actuel du système

  ✓ Suggérer des commandes que l’utilisateur peut exécuter. (Comme git status qui montre git add / restore)

  ✓ Les actions qui dépassent le périmètre interne du programme doivent être explicites. Par exemple lire/écrire des fichiers non demandés par l’utilisateur (cache), ou se connecter à un serveur distant (téléchargement de fichier)

  ✓ Utiliser l’art ASCII pour augmenter la densité d’information

  ✓ Utiliser la couleur avec intention. Ne pas en abuser

  ✓ Désactiver les couleurs si ce n’est pas un terminal ou si l’utilisateur le demande

  ✓ Si stdout n’est pas un terminal interactif, ne pas afficher d’animation

  ✓ N’utiliser symboles/emoji que lorsqu’ils clarifient quelque chose

  ✓ Par défaut, ne pas afficher d’informations que seul le créateur du programme peut comprendre

  ✓ Ne pas utiliser stderr comme un fichier de log (au moins pas par défaut. En mode verbeux, affichez plutôt des niveaux de log comme ERR, WARN)

  ✓ Si vous affichez beaucoup de texte, utiliser un outil de pagination comme less

 → Erreurs

  ✓ Intercepter les erreurs et réécrire les messages pour les humains

  ✓ Le ratio signal/bruit est important. Si la même erreur se produit plusieurs fois, regroupez-la avec un en-tête explicatif

  ✓ Réfléchir à l’endroit que l’utilisateur verra en premier

  ✓ En cas d’erreur inattendue/inexplicable, fournir des informations de debug/trace et expliquer comment envoyer ce bug aux développeurs

  ✓ Permettre l’envoi d’un rapport de bug sans effort supplémentaire. (Créer une URL contenant toutes les informations, pour que le signalement soit terminé rien qu’en l’ouvrant dans le navigateur)

 → Argument & Flags : arguments et flags

  ✓ Arguments : paramètres positionnels. L’ordre est important. cp bar foo et cp foo bar sont différents

  ✓ Flags : paramètres nommés. Une seule lettre comme -r ou plusieurs comme --recursive. L’ordre n’est généralement pas important.

        Ils peuvent aussi inclure une valeur utilisateur. --file foo.txt ou --file=foo.txt

  ✓ Préférer les flags aux arguments. Cela demande plus de frappe, mais c’est plus clair. Trop d’arguments compliquent l’évolution future

  ✓ Fournir à la fois une version courte et une version longue des flags. Dans les scripts, la version longue se comprend sans autre explication

  ✓ Réserver les flags à une lettre aux options les plus utilisées

  ✓ Pour des actions simples, accepter plusieurs arguments peut aussi convenir

  ✓ Si vous avez besoin de deux arguments ou plus qui soient distincts, vous faites peut-être quelque chose de travers

  ✓ Pour les flags, utiliser des noms standard quand ils existent déjà

    -a --all, -d --debug, -f --force, -h --help, -o --output, -p --port, -q --quiet, -u --user

  ✓ Choisir par défaut ce qui convient à la majorité des utilisateurs

  ✓ Si l’utilisateur a fourni un argument/flag qui requiert une valeur mais qu’aucune n’a été reçue, lui demander la saisie

  ✓ Toujours offrir un moyen de passer une valeur via arguments/flags, et ne pas imposer systématiquement une invite interactive

  ✓ Toujours demander confirmation avant une action dangereuse

  ✓ Si l’entrée ou la sortie est un fichier, prendre en charge - pour lire depuis stdin ou écrire vers stdout

    $ curl https://example.com/something.tar.gz | tar xvf -

  ✓ Si un flag peut recevoir une valeur supplémentaire, autoriser un mot spécial comme none. ssh -F none

  ✓ Si possible, rendre arguments, flags et sous-commandes indépendants de l’ordre

  ✓ Permettre de fournir les valeurs sensibles (comme les mots de passe) via un fichier

 → Interactivité

  ✓ N’utiliser les invites ou fonctionnalités interactives que lorsque stdin est un terminal interactif

  ✓ Si --no-input est passé, ne jamais utiliser d’invite ni de fonctionnalité interactive

  ✓ Lors de la saisie d’un mot de passe, ne pas afficher ce que l’utilisateur tape

  ✓ Permettre à l’utilisateur de quitter facilement (ne faites pas comme vim). Faire en sorte que Ctrl-C fonctionne. Si, comme avec ssh, tmux ou des programmes liés à l’exécution d’autres programmes, Ctrl-C est impossible, indiquer clairement qu’une séquence d’échappement commençant par ~ est disponible

 → Sous-commandes

  ✓ Les outils complexes peuvent réduire leur complexité grâce aux sous-commandes

  ✓ Si plusieurs outils sont étroitement liés, on peut aussi les regrouper dans une seule commande pour en simplifier l’usage

  ✓ Rester cohérent entre les sous-commandes. Un même flag doit garder le même sens, avec des formats de sortie similaires

  ✓ Utiliser des noms cohérents entre les différents niveaux de sous-commandes

  ✓ Éviter les commandes aux noms confus ou trop proches, comme update et upgrade

 → Robustesse

  ✓ Valider toutes les entrées utilisateur. Vérifier tôt et afficher des erreurs compréhensibles

  ✓ La réactivité est plus importante que la vitesse brute

  ✓ Si cela prend du temps, afficher la progression

  ✓ Si possible, traiter en parallèle. Mais le faire avec discernement

  ✓ Prévoir des timeouts

  ✓ Rendre l’outil idempotent (idempotent). (Le résultat ne change pas si on relance). En cas d’erreur, il doit être possible de reprendre simplement depuis le shell avec la flèche du haut

  ✓ Adopter une approche crash-only. Étape suivante après l’idempotence. Si aucun nettoyage n’est nécessaire après le travail, ou s’il peut être reporté à l’exécution suivante, le programme doit pouvoir s’arrêter immédiatement en cas d’échec ou d’interruption

  ✓ Les gens feront un mauvais usage de votre programme

 → Pérennité

  ✓ Dans la mesure du possible, faire évoluer de manière additive. Ne cassez pas la compatibilité en modifiant le comportement existant ; ajoutez plutôt de nouveaux flags

  ✓ Si un changement additif est impossible, avertissez d’abord

  ✓ Les changements de sortie destinés aux humains sont généralement acceptables

  ✓ Même si une sous-commande est la plus utilisée, ne créez pas de sous-commande fourre-tout qui l’exécute implicitement sans qu’elle soit indiquée

  ✓ Ne pas autoriser d’abréviations arbitraires de sous-commandes

  ✓ Ne pas introduire de « bombe à retardement » qui finira par ne plus fonctionner un jour

 → Signaux et caractères de contrôle

  ✓ Quand l’utilisateur tape Ctrl-C (signal INT), interrompre aussi vite que possible

  ✓ Si l’utilisateur appuie sur Ctrl-C pendant une phase de nettoyage longue, l’ignorer une première fois, puis permettre une sortie forcée à la seconde

     ^CGracefully stopping... (press Ctrl+C again to force)

 → Configuration

  ✓ Respecter la spécification XDG(X Desktop Group)

  ✓ Si vous modifiez une configuration qui n’appartient pas à votre programme, demandez confirmation à l’utilisateur et expliquez clairement ce que vous faites

  ✓ Appliquer les paramètres de configuration selon l’ordre de priorité

    flags > variables d’environnement du shell > configuration au niveau du projet (.env) > configuration utilisateur > configuration système

 → Variables d’environnement

  ✓ Les variables d’environnement servent aux comportements qui dépendent du contexte d’exécution de la commande

  ✓ Pour maximiser la portabilité, les variables d’environnement ne doivent contenir que des majuscules, des chiffres et des soulignés, et ne doivent pas commencer par un chiffre

  ✓ Si possible, utiliser des valeurs sur une seule ligne (single-line) dans les variables d’environnement

  ✓ Ne pas utiliser de noms largement répandus

  ✓ Si possible, vérifier et utiliser les variables d’environnement génériques

    NO_COLOR, DEBUG, EDITOR, HTTP_PROXY, SHELL, TERM, TERMINFO, HOME, TMPDIR, PAGER, LINES ..

  ✓ Si nécessaire, charger les variables d’environnement depuis .env

  ✓ Ne pas utiliser l’extension .env pour les fichiers de configuration

 → Nommage

  ✓ Choisir des noms simples et faciles à mémoriser

  ✓ N’utiliser que des minuscules, et n’employer - (tiret) qu’en cas de nécessité

  ✓ Aussi court que possible

  ✓ Facile à taper au clavier

 → Distribution

  ✓ Si possible, distribuer sous la forme d’un binaire unique

  ✓ Faciliter la désinstallation

 → Analytics

  ✓ N’envoyez pas vos données d’usage ou de crash sans le consentement de l’utilisateur

3 commentaires

 
jonnung 2021-01-09

Merci pour ce bon contenu.

 
xguru 2020-12-28

Il semble que Rust et Go, qui facilitent la création de binaires uniques bien conçus, favorisent l’apparition d’un nombre croissant de bons outils en ligne de commande.

Les créer devient aussi de plus en plus simple et puissant.

 
xguru 2020-12-28

J’ai beaucoup appris en faisant cette traduction assez simplement. Après coup… je me dis qu’il aurait peut-être mieux valu traduire le dépôt lui-même. ^^;;