<< Retour à la liste d'articles

Dans un projet, il est important d'avoir une écriture du code claire et structuré pour que les éventuels reprises ou modification de code soient moins complexe à effectué par une autre personne
Les points suivants sont là pour mettre en avant des pratiques qui permettent d'avoir un code claire pour un maximum de personnes et qui permet de faire ressortir rapidement l'idée d'un bloc de code
Il est aussi important de garder un code homogène au sein d'un script mais aussi globalement au sein des différents scripts
Ecriture des blocs conditionnels
Format 1
if [ cond1 ] || [ cond2 ] ; then
  instruction
fi
for element in ${list} ; do
  instruction
done
while [ cond ] ; do
  instruction
done
Format 2
if [ cond1 ] || [ cond2 ]
then
  instruction
fi
for element in $list
do
  instruction
done
while [ cond ]
do
  instruction
done
Format 3
Il est préférable de garder ce format très simpliste : une seule condition suivi d'une seule instruction, voire deux si la 2ème est un 'exit' ou un 'return'
[ cond ] && instruction
Ce format est bien pour faire des sorties conditionnels avec message
[ "${NAME}" == "" ] && echo "Erreur : NAME non fournit" && exit 1
Il est aussi préférable d'éviter les doublons de condition
[ cond ] && instruction1
[ cond ] && instruction2
[ ! cond ] && instruction3
Il est plus claire pour la compréhension d'utiliser les formats 1 ou 2 avec 'else'
if [ cond ] ; then
  instruction1
  instruction2
else
  instruction3
fi
Ecriture des variables
Il est important de bien choisir ses noms de variable pour la compréhension globale du code
Nom plus claire pour une relecture extérieur
un exemple de nom à éviter : ${tmp}, ${temp}; ici on comprends qu'il y a une notion d'éphémère mais on ne sait pas quoi.
Est-ce le contenu de la variable tmp qui est temporaire ?
Est-ce un fichier temporaire ?
Est-ce un dossier temporaire ?
${tmp_file} est beaucoup plus explicite, ${tmp_log_file} ou ${tmp_work_file} le sont encore plus
/!\ Attention à ne pas tomber non plus dans l'excès des variables trop longues /!\
Evolution moins lourde du script
Autre exemple avec la variable ${nb}
Aujourd'hui, le script ne fait que compter une seule chose, ${nb} convient parfaitement pour contenir un nombre.
Mais demain, si le script évolue avec le besoin de compter d'autre chose et faire un rapport à la fin ?
Quel nom choisir pour cette 2ème variable ?
- ${count} ? pour un relecteur extérieur la différence entre ${nb} et ${count} n'est pas explicite, il devra se rappeler constamment quel variable correspond à quel information.
- ${nb2} ? même problème que ${count}
- ${nb_colonnes} ? c'est mieux, mais maintenant, on a 2 variables ${nb} et ${nb_colonnes} donc, pour garder un code explicite, il faudra renommer toute les occurences de ${nb}, qui ne devient plus aussi évident que dans la version précédente
Préférer l'écriture ${var} plutôt que $var
Permet d'éviter certaine confusions de nom de variable
Permet de faire mieux ressortir visuellement les parties variables de certains blocs de code
Permet d'appliquer des modifications rapide et de masse sur un nom de variable sans se soucier d'éventuels faux positifs
Déclaration des fonctions
Le mot clé 'function' n'étant pas reconnu partout, il est plus portable d'utiliser le format suivant :
function() {
  instructions
}
Redirection et pipes en cascades
Lorsque plusieurs processus sont lancé en cascade par des pipes, il est beaucoup plus rapide pour un autre développeur de comprendre ce qui est fait si chaque processus "pipé" est sur une ligne différente
Exemple :
selchamp R chp=id_origine table=${TMP_DIR}/amasqlo.ama_origine_contact.stru cle=id_origine_contact < fichier.IN | grep -v toto | reforme id_origine id_newsletter="'${count}'" | rchamp chp=id_newsletter table=${TMP_DIR}/amasqlo.ama_newsletter.stru cle=id_newsletter -ajout | reforme id_origine id_newsletter | grep -v toto | destru -supent -e'\n' >> fichier.OUT
Devient bien plus lisible rapidement si on l'écrit comme suit :
selchamp R chp=id_origine table=${TMP_DIR}/amasqlo.ama_origine_contact.stru cle=id_origine_contact < fichier.IN \
| grep -v toto \
| reforme id_origine id_newsletter="'${count}'" \
| rchamp chp=id_newsletter table=${TMP_DIR}/amasqlo.ama_newsletter.stru cle=id_newsletter -ajout \
| reforme id_origine id_newsletter \
| grep -v toto \
| destru -supent -e'\n' \
>> fichier.OUT
On peut aisément distinguer chaque étape de transformation et permet de voir rapidement que dans cette exemple, l'étape "grep -v toto" est présente 2 fois alors qu'une fois suffit
Optimisation du code
L'optimisation d'un code shell est évidemment LOIN d'être une priorité, mais si on peut le faire bien et sans effort supplémentaire, dès le départ, c'est mieux.
Le besoin de rapidité de traitement, n'est peut-être pas un besoin actuel, mais peut le devenir plus tard.
Ce qui coute le plus cher dans un script sont les éventuels accès disque écriture et lecture, et le nombre de création de processus, le coût en RAM n'est pas pertinant car minime
Evidemment, ceci n'est pas une règle absolue, tout dépendant des traitements lancés par le script.
Nombre de processus lancés
Exemple avec une condition créant 3 processus système, 3 flux de sortie, 2 analyses de flux :
[ $(cat $file | grep -e ${name} | wc -l) -eq 0 ] && echo "Erreur !" && exit
Peut être remplacé par :
[ $(grep -c "${name}" $file) -eq 0 ] && echo "Erreur !" && exit
Qui ne créer qu' 1 processus système, 1 analyse de flux, 1 flux de sortie
Nombre de traitement doublons
L'exemple suivant:
if [ $(grep -c "${name}" ${file}) -ne 0 ] ; then
  echo "Nombre : $(grep -c '${name}' ${file})"
fi
Peut être remplacé par :
nb_name=$(grep -c "${name}" ${file})
if [ ${nb_name} -ne 0 ] ; then
  echo "Nombre : ${nb_name}"
fi
L'exemple suivant:
[ $(grep -c "${name}" ${file}) -eq 0 ] && echo "Cool !"
[ ! $(grep -c "${name}" ${file}) -eq 0 ] && echo "Pas Cool !"
Peut être remplacé par un if else qui apporte aussi plus de clareté dans le code
if [ $(grep -c "${name}" ${file}) -eq 0 ] ; then
  echo "Cool !"
else
  echo "Pas cool !"
fi
<< Retour à la liste d'articles

[17/01/19]