35. Écrire des scripts avec style

Prenez l'habitude d'écrire vos scripts shell d'une façon structurée et méthodique. Même des scripts écrits à la va-vite, « sur un petit bout de papier », seront souvent bien meilleurs si vous prenez le temps de planifier et d'organiser vos pensées avant de vous asseoir pour coder.

Voici quelques recommandations stylistiques. Elles n'ont pas (forcément) pour but de devenir la feuille de style officielle des scripts Shell.

35.1. Feuille de style non officielle d'écriture de scripts

  • Commentez votre code. Cela le rend plus facile à comprendre (et apprécier) par les autres, et plus facile pour vous à maintenir.

    PASS="$PASS${MATRIX:$(($RANDOM%${#MATRIX})):1}"
    #  Cela avait un sens lorsque vous l'aviez écrit l'année dernière, mais
    #+ c'est un mystère complet.
    # (À partir du script "pw.sh" de Antek Sawicki.)
    

    Ajoutez des en-têtes descriptives à votre script et à vos fonctions.

    #!/bin/bash
    
    #************************************************#
    #                   xyz.sh                       #
    #          écrit par by Bozo Bozeman             #
    #                05 Juil. 2001                   #
    #                                                #
    #   Faire le ménage dans les fichiers projets.    #
    #************************************************#
    
    E_MAUVAISREPERTOIRE=85          # Répertoire inexistant.
    rep_projets=/home/bozo/projets  # Répertoire à nettoyer.
    
    # ----------------------------------------------------------- #
    # nettoie_pfichiers ()                                        #
    # Supprime tous les fichiers dans le répertoire indiqué.      #
    # Paramètre : $repertoire_cible                               #
    # Renvoie   : 0 en cas de succès, $E_MAUVAISREPERTOIRE sinon. #
    # ----------------------------------------------------------- #
    nettoie_pfichiers ()
    {
      if [ ! -d "$1" ]  # Teste si le répertoire cible existe.
      then
        echo "$1 n'est pas un répertoire."
        return $E_MAUVAISREPERTOIRE
      fi
    
      rm -f "$1"/*
      return 0   # Succès.
    }
    
    nettoie_pfichiers $rep_projets
    
    exit $?
    
  • Éviter d'utiliser les « nombres magiques », [120] c'est-à-dire des constantes littérales « codées en dur ». Utilisez des noms de variables significatifs à la place. Ceci rend le script plus facile à comprendre et permet de faire des changements et des mises à jour sans casser l'application.

    if [ -f /var/log/messages ]
    then
      ...
    fi
    # Un an après, vous décidez de modifier le script pour vérifier /var/log/syslog.
    #  Alors il faut modifier manuellement le script, instance par
    #+ instance, et espérer que rien ne va casser.
    
    # Voici un meilleur moyen :
    FICHIERTRACE=/var/log/messages  # Seule une ligne a besoin d'être modifié.
    if [ -f "$FICHIERTRACE" ]
    then
      ...
    fi
    
  • Choisissez des noms descriptifs pour les variables et les fonctions.

    fl=`ls -al $nomrep`                  # Crypté.
    liste_fichiers=`ls -al $nomrep`      # Mieux.
    
    
    VALMAX=10   # Tout en majuscule pour les constantes du script.
    while [ "$index" -le "$VALMAX" ]
    ...
    
    
    E_PASTROUVE=95                       # Tout en majuscule pour les codes d'erreur,
                                         #+ et leur nom préfixé par "E_".
    if [ ! -e "$nomfichier" ]
    then
      echo "Fichier $nomfichier introuvable."
      exit $E_PASTROUVE
    fi
    
    
    REPERTOIRE_MAIL=/var/spool/mail/bozo # Tout en majuscule
    export REPERTOIRE_MAIL               #+ pour une variable d'environnement.
    
    
    ObtientReponse ()                    # Majuscule et minuscule pour une
    {                                                                        #+ fonction, en particulier quand
      invite=$1                                                      #+ cela améliore la lisibilité.
      echo -n $invite
      read reponse
      return $reponse
    }
    
    ObtientReponse "Quel est votre nombre favori ? "
    nombre_favori=$?
    echo $nombre_favori
    
    
    _variableutilisateur=23              # OK, mais pas recommandé.
    #  Il est mieux pour les variables définies par les utilisateurs de ne pas
    #+ commencer avec un tiret bas.
    # Laissez cela pour les variables système.
    
  • Utiliser des codes de sortie d'une façon systématique et significative.

    E_MAUVAIS_ARGS=95
    ...
    ...
    exit $E_MAUVAIS_ARGS
    

    Voir aussi l'Annexe D, Codes de sortie ayant une signification particulière.

    Ender suggère d'utiliser les codes de sortie contenus dans /usr/include/sysexits.h dans les scripts shell, bien qu'ils soient destinés avant tout à la programmation en C et C++.

  • Utilisez les options de paramètres standardisées pour l'appel de script. Ender propose l'ensemble d'options suivant.

    -a      All: renvoie toutes les informations
            (incluant les informations de fichiers cachés).
    -b      Bref: Version courte, généralement pour les autres scripts.
    -c      Copie, concatène, etc.
    -d      Daily: Utilise l'information du jour complet et non pas seulement
            l'information pour une instance ou pour un utilisateur spécifique.
    -e      Étendu/Élaboré: (n'inclut souvent pas les informations de fichiers
            cachés).
    -h      Help: Aide, indication verbeuse sur l'utilisation avec description,
            discussion, aide.
            Voir aussi -V.
    -l      Traces du script.
    -m      Manuel: page man de la commande de base.
    -n      Nombre: Données numériques seulement.
    -r      Récursif: Tous les fichiers d'un répertoire (et/ou tous les
            sous-répertoires).
    -s      Setup & Maintenance fichier: Fichier de configuration de ce script.
    -u      Usage: Liste des options à l'appel du script.
    -v      Verbeux: Sortie lisible par un humain, plus ou moins formaté.
    -V      Version / Licence / Copy(right|left) / Contributions (par courrier
            électronique aussi).
    

    Voir aussi l'Section F.1, « Options standards en ligne de commande ».

  • Scinder les scripts complexes en modules plus simples. Utiliser des fonctions quand c'est approprié. Voir l'Exemple 37.4, « Utiliser des tableaux et autres astuces pour gérer quatre mains aléatoires dans un jeu de cartes ».

  • N'utilisez pas une construction complexe lorsqu'une construction plus simple fait l'affaire.

    COMMANDE
    if [ $? -eq 0 ]
    ...
    # Redondant et non intuitif.
    
    if COMMANDE
    ...
    # Plus concis (même si moins compréhensible).
    

... reading the UNIX source code to the Bourne shell (/bin/sh). I was shocked at how much simple algorithms could be made cryptic, and therefore useless, by a poor choice of code style. I asked myself, « Could someone be proud of this code? »

... en lisant le code source UNIX du Bourne Shell (/bin/sh), j'ai éprouvé un choc en constatant à quel point de simples algorithmes pouvaient être rendus incompréhensibles, et du coup inutiles, par un mauvais choix dans le style de codage. Je me suis alors demandé : « Quelqu'un peut-il être fier de ce code ? »



[120] Dans ce contexte, les « nombres magiques  » ont une signification entièrement différente que les nombres magiques utilisés pour désigner les types de fichier.