Ecrire du php lisible
Par jcm, dimanche 10 juillet 2011 à 22:39 :: General :: #114 :: rss
Lorsque vous passez vos journées à travailler des scripts réalisés par diverses personnes d'une équipe (un script est un fichier informatique contenant des éléments d'un programme, ce dernier étant destiné à faire fonctionner un site web par exemple ou tout type de logiciel) vous êtes confronté à la question de la lisibilité de ces scripts.
Un script peut contenir très peu de lignes de code, effectuer une tâche simple, il peut aussi être très long et réaliser des processus très complexes.
La lisibilité d'un script peut être envisagée sous deux aspects : la façon selon laquelle il est présenté et la façon dont l'algorithme est construit.
C'est le premier aspect qui retient ici mon attention.
Il a été réalisé de très nombreuses études sur la lisibilité d'un texte.
Leurs conclusions peuvent s'appliquer à n'importe quel texte et par conséquent aux scripts informatiques car elles font état de nos capacités à discerner et appréhender de façon plus ou moins aisées les informations contenues dans un texte.
Elles renvoient aux facultés que nous mobilisons pour déchiffrer, et l'on ne déchiffre pas un même texte avec la même aisance selon qu'il emprunte telle ou telle règle d'écriture : cela signifie qu'accéder à une bonne compréhension de ce qu'on lit sera plus ou moins facile, plus ou moins fatigant, plus ou moins couronné de succès puisque plus la lecture est difficile plus il devient facile de se méprendre sur le sens de ce qu'on lit.
L'élément de base de notre écriture est le mot (« suite de sons ou de caractères graphiques formant une unité sémantique et pouvant être distingués par un séparateur » ) : on voit ici le caractère essentiel de la présence d'une unité « le séparateur » qui effectue la coupure d'un texte en ses unités élémentaires et permet de distinguer les « mots ».
Le séparateur définit le mot : est-ce uniquement de la théorie ?
Expérimentons cela :
« Lemotfrançaisdérivedubas-latinmuttum.Ils'agitd'unsubstantifduverbelatinmuttiredontlasignificationresteobscure.
Ceverbeindiquegénéralementlaproductiond'undiscoursinarticuléet/ouincohérent:ausenspropre,muttire,c'estdiremu,soitgrognercommeunbovin.
Toutefois,ildéfinitégalementlecontraire,soitlaformulationd'unénoncéarticulé.
Dèssonorigine,lemotsetrouvechargéd'unetensionsémantiqueettirailléentredeuxsignificationscontradictoires. »
Sans séparateurs un texte devient très difficile à lire, les différents niveaux de morphèmes () ne peuvent plus être distingués et l'on se trouve face à une sorte de magma de lettres que, finalement, personne ne souhaiterait lire.
L'espace est-il le seul séparateur acceptable ?
« Le#mot#français#dérive#du#bas-latin#muttum.#Il#s'agit#d'un#substantif#du#verbe#latin#muttire#dont#la#signification#reste#obscure.
#Ce#verbe#indique#généralement#la#production#d'un#discours#inarticulé#et/ou#incohérent#:#au#sens#propre,#muttire,#c'est#dire#mu,#soit#grogner#comme#un#bovin.
#Toutefois,#il#définit#également#le#contraire,#soit#la#formulation#d'un#énoncé#articulé.
#Dès#son#origine,#le#mot#se#trouve#chargé#d'une#tension#sémantique#et#tiraillé#entre#deux#significations#contradictoires. »
Difficile de lui trouver un substitut aussi efficace...
On constate donc ici que l'individualisation des mots par un séparateur dont la forme est constante et qui se distingue facilement de tout autre caractère typographique est essentielle pour une bonne lisibilité.
Une autre petite expérience nous montre la très grande efficacité de l'espace vide comme séparateur de mots :
« on lit aessz bein un ttxee cnanetnot des mtos dont les cerèarctas ienretns ont été iesrevns de foçan suqitamétsye cmome ccei. »
L'inversion ou le mélange des lettres internes à un mot n'est pas vraiment plus pénalisante que l'absence de séparateurs vue plus haut, cela est dû à la capacité de notre cerveau à effectuer certaines reconstitutions par rapport à des informations confuses : admettons que la facilité n'est pas vraiment au rendez-vous... et que l'on peut faire pire :
« onlitaesszbeinunttxeecnanetnotdesmtosdontlescerèarctasienretnsontétéiesrevnsdefoçansuqitamétsyecmomeccei. »
C'était le même sans séparateur...
Ce ne sont pas les seules obstacles à une bonne lecture, ainsi :
« EN LINGUISTIQUE, ON DÉFINIT GÉNÉRALEMENT UN MORPHÈME COMME LA PLUS PETITE UNITÉ PORTEUSE DE SENS QU'IL SOIT POSSIBLE D'ISOLER DANS UN ÉNONCÉ. DE MÊME QUE LE PHONÈME, LE MORPHÈME EST UNE ENTITÉ ABSTRAITE SUSCEPTIBLE DE SE RÉALISER DE PLUSIEURS MANIÈRES DANS LA CHAÎNE PARLÉE. »
Il a été démontré qu'un texte en capitales est plus difficile à lire, et donne lieu à plus d'erreurs de compréhension, que le même texte en minuscules.
Revenons maintenant à nos scripts php.
On y trouve souvent :
if(isset($trux)&&$trux!=0&&$monTrucquiFaitTruc!==true&&$cetrucla='machin'){$lautreTruc=true;}
if(isset($chosex)&&$chosex!=0&&$monchosecquiFaitchosec!==true&&$cechosecla='machin'){$lautrechosec='chosee';}
Est-ce lisible ?
if ( isset($trux) && $trux != 0 && $monTrucquiFaitTruc !== true && $cetrucla = 'machin' ) { $lautreTruc = true; }
if ( isset($chosex) && $chosex! = 0 && $monchosecquiFaitChosec !== true && $cechosecla = 'machin' ) { $lautrechosec = 'chosee'; }
N'est-ce pas plus lisible ?
La raison en est que chaque « mot » est bel et bien individualisé par le séparateur standard utilisé dans notre langue.
Détaillons ce que sont des « mots » dans ce cas : ce sont tous les éléments qui ont un « sens » intrinsèque (des « unités de sens »), ce sont ici :
les variables : tout ce qui est compris entre deux séparateurs et qui est précédé de « $ »
les éléments de syntaxe de programmation : ( ) { } = != !== &&
les fonctions de programmation : isset( par exemple.
On notera qu'il y a une différence entre « ( ) { } = != !== && » et « (){}=!=!==&& » car si dans le premier cas on peut détecter facilement des « mots » comme « } » dans le second on ne sait pas si « !=! » est un « mot ».
Seule la connaissance du langage php nous permet de tirer un sens de la seconde proposition car on sait alors que « !=! » ne peut pas être un « mot » acceptable comme tel dans ce cas.
Pour déchiffrer correctement la seconde proposition il faut donc faire un effort complémentaire à celui de la simple lecture : il faut ajouter une tâche de décodage (effort supplémentaire), qui se traduit en un gaspillage d'énergie, de temps, en un accroissement de fatigue et en moindre efficacité.
Dans le cas d'un travail en entreprise, assez éloigné de tout loisir, ces inconvénients devraient être systématiquement évités.
Définir des « mots » php
On peut écrire ceci, car l'interpréteur php le traitera correctement (malheureusement pour le lecteur humain) :
$monAutreMachin=substr($monMachinquiFaitTruc,'0','8');
or cela n'est qu'un seul et unique « mot » au sens linguistique du terme, mais il contient en fait plusieurs « mots » en langage php.
$monAutreMachin = substr($monMachinquiFaitTruc, '0', '8'); sera plus immédiatement lisible car chaque « mot » est immédiatement identifiable.
On trouvera aussi :
$monAutreMachin=str_replace('\'','u',$monMachinquiFaitTruc);
au lieu de
$monAutreMachin = str_replace('\'', 'u', $monMachinquiFaitTruc);
Imaginez cela parmi des dizaines ou centaines de lignes de code : dans le premier cas une confusion assez probable, dans le second des « mots » faciles à identifier qui permettent une lecture beaucoup plus fluide.
Camelized or not ?
Ah quelle invention que cette saleté !
L'écriture en « dos de chameau » est basée sur une alternance de majuscules et minuscules et permet d'écrire « $monMachinquiFaitTruc », expression dans laquelle on remarquera qu'une certaine intention a présidé à son écriture car on y détecte que le « machin » doit faire quelque-chose et qu'il s'agit de « truc ».
Ainsi en javascript on trouve l'expression bien connue « document.getElementsByTagName » qui, prise isolément, demeure à peu près lisible mais dans le cadre d'un script dense donne des suites de lignes à peu près illisibles sans un bon effort de concentration, notamment parce-se cela pourra être suivi de « document.getElementsByTId » et autres « document.trucmucheLeZinzinouEquivalent ».
Tout simplement parce-que des expressions comme « getElementsByTagName » ne comportent aucun séparateur.
Les concepteurs de php ont dû avoir conscience de cet aspect des choses, eux qui ont mis à notre disposition des fonctions comme :
str_getcsv
str_ireplace
str_pad
str_repeat
str_replace
str_rot13
str_shuffle
str_split
str_word_count
dans lesquelles un séparateur « _ » bien placé découpe les expressions en « mots » et nous facilite la lecture.
Car nous aurions pu avoir un magma verbeux du type javascript comme :
strGetDocumentCsv
strInsensitiveReplace
stringPad
strRepeatString
strReplaceInside
strTransformToROT13
strShuffleContent
strSplitIntoArray
strWordCount
(et pourquoi pas « strReplaceInsideTheStrEnQuestion » ?)
Où est le plus lisible ?
Heureusement en javascript quelques scripts nous permettent de nous passer du « document.getElementsByTagName » en nous permettant d'écrire « $('le nom de tag de l'élément') » donc par exemple : $('machin').
C'est le cas de la lourdingue et rigide « prototype », de la plus flexible et modulaire « jQuery » et de quelque autres.
Dans le domaine où j'exerce aujourd'hui, la programmation de sites de covoiturage, il est souvent question de variables concernant un lieu de départ ou d'arrivée, de dates et d'heures...
C'est pourquoi j'ai pris des noms de variables dans ce domaine, voyons donc ce qui est possible :
On peut écrire :
if($maDateArrivee!=0&&$maDateDepart!=0&&$monLieuArrivee!=''&&$monLieuDépart!=''&&$monIdentifiantIsCertified==true){ $onContinueLaProcedure=true;}
C'est du camélisé sans séparateur.
Mais cela peut également s'écrire :
if ( $date_arr != 0 && $date_dep != 0 && $lieu_arr != '' && $lieu_dep != '' && $id_cert == true ) { $continue = true; }
pour une meilleure lisibilité.
Le programmeur qui écrira ses scripts en omettant systématiquement les séparateurs (peut-être afin de gagner le temps en ne frappant pas la barre d'espace ?) fera toujours perdre du temps, et sera la cause de probables erreurs d'interprétation (éventuellement pour lui-même dans l'avenir), car il aura écrit de l'illisible en mode de « lecture naturelle » : il imposera à tout lecteur un effort supplémentaire à celui de la seule lecture, afin que le lecteur trouve la place que devraient avoir les séparateurs pour reconstituer correctement les mots, et finalement accéder au sens du texte.
Par ailleurs notons une différence entre « $maDateArrivee, $maDateDepart » et « $date_arr, $date_dep » : vous aurez noté que le « ma » a disparu de la dernière formulation.
Je ne sais d'où vient ce « ma », « mon », « mes » devant un certain nombre de variables utilisées ici ou là, mais il est strictement inutile car sans signification et ajoute de la surcharge inutile.
C'est ce que l'on retrouve dans les dossiers de systèmes d'exploitation et n'a absolument aucun sens.
Qu'un dossier sur un ordinateur s'appelle « Mes documents » ne signifie pas que celui qui accédera à ce dossier le possède réellement...
Bien des informaticiens semblent ignorer que « Le moi est haïssable » (Pascal)...
A lire : « Les geeks sont-ils anti “intellectuels”? »
Un script peut contenir très peu de lignes de code, effectuer une tâche simple, il peut aussi être très long et réaliser des processus très complexes.
La lisibilité d'un script peut être envisagée sous deux aspects : la façon selon laquelle il est présenté et la façon dont l'algorithme est construit.
C'est le premier aspect qui retient ici mon attention.
Il a été réalisé de très nombreuses études sur la lisibilité d'un texte.
Leurs conclusions peuvent s'appliquer à n'importe quel texte et par conséquent aux scripts informatiques car elles font état de nos capacités à discerner et appréhender de façon plus ou moins aisées les informations contenues dans un texte.
Elles renvoient aux facultés que nous mobilisons pour déchiffrer, et l'on ne déchiffre pas un même texte avec la même aisance selon qu'il emprunte telle ou telle règle d'écriture : cela signifie qu'accéder à une bonne compréhension de ce qu'on lit sera plus ou moins facile, plus ou moins fatigant, plus ou moins couronné de succès puisque plus la lecture est difficile plus il devient facile de se méprendre sur le sens de ce qu'on lit.
L'élément de base de notre écriture est le mot (« suite de sons ou de caractères graphiques formant une unité sémantique et pouvant être distingués par un séparateur » ) : on voit ici le caractère essentiel de la présence d'une unité « le séparateur » qui effectue la coupure d'un texte en ses unités élémentaires et permet de distinguer les « mots ».
Le séparateur définit le mot : est-ce uniquement de la théorie ?
Expérimentons cela :
« Lemotfrançaisdérivedubas-latinmuttum.Ils'agitd'unsubstantifduverbelatinmuttiredontlasignificationresteobscure.
Ceverbeindiquegénéralementlaproductiond'undiscoursinarticuléet/ouincohérent:ausenspropre,muttire,c'estdiremu,soitgrognercommeunbovin.
Toutefois,ildéfinitégalementlecontraire,soitlaformulationd'unénoncéarticulé.
Dèssonorigine,lemotsetrouvechargéd'unetensionsémantiqueettirailléentredeuxsignificationscontradictoires. »
Sans séparateurs un texte devient très difficile à lire, les différents niveaux de morphèmes () ne peuvent plus être distingués et l'on se trouve face à une sorte de magma de lettres que, finalement, personne ne souhaiterait lire.
L'espace est-il le seul séparateur acceptable ?
« Le#mot#français#dérive#du#bas-latin#muttum.#Il#s'agit#d'un#substantif#du#verbe#latin#muttire#dont#la#signification#reste#obscure.
#Ce#verbe#indique#généralement#la#production#d'un#discours#inarticulé#et/ou#incohérent#:#au#sens#propre,#muttire,#c'est#dire#mu,#soit#grogner#comme#un#bovin.
#Toutefois,#il#définit#également#le#contraire,#soit#la#formulation#d'un#énoncé#articulé.
#Dès#son#origine,#le#mot#se#trouve#chargé#d'une#tension#sémantique#et#tiraillé#entre#deux#significations#contradictoires. »
Difficile de lui trouver un substitut aussi efficace...
On constate donc ici que l'individualisation des mots par un séparateur dont la forme est constante et qui se distingue facilement de tout autre caractère typographique est essentielle pour une bonne lisibilité.
Une autre petite expérience nous montre la très grande efficacité de l'espace vide comme séparateur de mots :
« on lit aessz bein un ttxee cnanetnot des mtos dont les cerèarctas ienretns ont été iesrevns de foçan suqitamétsye cmome ccei. »
L'inversion ou le mélange des lettres internes à un mot n'est pas vraiment plus pénalisante que l'absence de séparateurs vue plus haut, cela est dû à la capacité de notre cerveau à effectuer certaines reconstitutions par rapport à des informations confuses : admettons que la facilité n'est pas vraiment au rendez-vous... et que l'on peut faire pire :
« onlitaesszbeinunttxeecnanetnotdesmtosdontlescerèarctasienretnsontétéiesrevnsdefoçansuqitamétsyecmomeccei. »
C'était le même sans séparateur...
Ce ne sont pas les seules obstacles à une bonne lecture, ainsi :
« EN LINGUISTIQUE, ON DÉFINIT GÉNÉRALEMENT UN MORPHÈME COMME LA PLUS PETITE UNITÉ PORTEUSE DE SENS QU'IL SOIT POSSIBLE D'ISOLER DANS UN ÉNONCÉ. DE MÊME QUE LE PHONÈME, LE MORPHÈME EST UNE ENTITÉ ABSTRAITE SUSCEPTIBLE DE SE RÉALISER DE PLUSIEURS MANIÈRES DANS LA CHAÎNE PARLÉE. »
Il a été démontré qu'un texte en capitales est plus difficile à lire, et donne lieu à plus d'erreurs de compréhension, que le même texte en minuscules.
Revenons maintenant à nos scripts php.
On y trouve souvent :
if(isset($trux)&&$trux!=0&&$monTrucquiFaitTruc!==true&&$cetrucla='machin'){$lautreTruc=true;}
if(isset($chosex)&&$chosex!=0&&$monchosecquiFaitchosec!==true&&$cechosecla='machin'){$lautrechosec='chosee';}
Est-ce lisible ?
if ( isset($trux) && $trux != 0 && $monTrucquiFaitTruc !== true && $cetrucla = 'machin' ) { $lautreTruc = true; }
if ( isset($chosex) && $chosex! = 0 && $monchosecquiFaitChosec !== true && $cechosecla = 'machin' ) { $lautrechosec = 'chosee'; }
N'est-ce pas plus lisible ?
La raison en est que chaque « mot » est bel et bien individualisé par le séparateur standard utilisé dans notre langue.
Détaillons ce que sont des « mots » dans ce cas : ce sont tous les éléments qui ont un « sens » intrinsèque (des « unités de sens »), ce sont ici :
les variables : tout ce qui est compris entre deux séparateurs et qui est précédé de « $ »
les éléments de syntaxe de programmation : ( ) { } = != !== &&
les fonctions de programmation : isset( par exemple.
On notera qu'il y a une différence entre « ( ) { } = != !== && » et « (){}=!=!==&& » car si dans le premier cas on peut détecter facilement des « mots » comme « } » dans le second on ne sait pas si « !=! » est un « mot ».
Seule la connaissance du langage php nous permet de tirer un sens de la seconde proposition car on sait alors que « !=! » ne peut pas être un « mot » acceptable comme tel dans ce cas.
Pour déchiffrer correctement la seconde proposition il faut donc faire un effort complémentaire à celui de la simple lecture : il faut ajouter une tâche de décodage (effort supplémentaire), qui se traduit en un gaspillage d'énergie, de temps, en un accroissement de fatigue et en moindre efficacité.
Dans le cas d'un travail en entreprise, assez éloigné de tout loisir, ces inconvénients devraient être systématiquement évités.
Définir des « mots » php
On peut écrire ceci, car l'interpréteur php le traitera correctement (malheureusement pour le lecteur humain) :
$monAutreMachin=substr($monMachinquiFaitTruc,'0','8');
or cela n'est qu'un seul et unique « mot » au sens linguistique du terme, mais il contient en fait plusieurs « mots » en langage php.
$monAutreMachin = substr($monMachinquiFaitTruc, '0', '8'); sera plus immédiatement lisible car chaque « mot » est immédiatement identifiable.
On trouvera aussi :
$monAutreMachin=str_replace('\'','u',$monMachinquiFaitTruc);
au lieu de
$monAutreMachin = str_replace('\'', 'u', $monMachinquiFaitTruc);
Imaginez cela parmi des dizaines ou centaines de lignes de code : dans le premier cas une confusion assez probable, dans le second des « mots » faciles à identifier qui permettent une lecture beaucoup plus fluide.
Camelized or not ?
Ah quelle invention que cette saleté !
L'écriture en « dos de chameau » est basée sur une alternance de majuscules et minuscules et permet d'écrire « $monMachinquiFaitTruc », expression dans laquelle on remarquera qu'une certaine intention a présidé à son écriture car on y détecte que le « machin » doit faire quelque-chose et qu'il s'agit de « truc ».
Ainsi en javascript on trouve l'expression bien connue « document.getElementsByTagName » qui, prise isolément, demeure à peu près lisible mais dans le cadre d'un script dense donne des suites de lignes à peu près illisibles sans un bon effort de concentration, notamment parce-se cela pourra être suivi de « document.getElementsByTId » et autres « document.trucmucheLeZinzinouEquivalent ».
Tout simplement parce-que des expressions comme « getElementsByTagName » ne comportent aucun séparateur.
Les concepteurs de php ont dû avoir conscience de cet aspect des choses, eux qui ont mis à notre disposition des fonctions comme :
str_getcsv
str_ireplace
str_pad
str_repeat
str_replace
str_rot13
str_shuffle
str_split
str_word_count
dans lesquelles un séparateur « _ » bien placé découpe les expressions en « mots » et nous facilite la lecture.
Car nous aurions pu avoir un magma verbeux du type javascript comme :
strGetDocumentCsv
strInsensitiveReplace
stringPad
strRepeatString
strReplaceInside
strTransformToROT13
strShuffleContent
strSplitIntoArray
strWordCount
(et pourquoi pas « strReplaceInsideTheStrEnQuestion » ?)
Où est le plus lisible ?
Heureusement en javascript quelques scripts nous permettent de nous passer du « document.getElementsByTagName » en nous permettant d'écrire « $('le nom de tag de l'élément') » donc par exemple : $('machin').
C'est le cas de la lourdingue et rigide « prototype », de la plus flexible et modulaire « jQuery » et de quelque autres.
Dans le domaine où j'exerce aujourd'hui, la programmation de sites de covoiturage, il est souvent question de variables concernant un lieu de départ ou d'arrivée, de dates et d'heures...
C'est pourquoi j'ai pris des noms de variables dans ce domaine, voyons donc ce qui est possible :
On peut écrire :
if($maDateArrivee!=0&&$maDateDepart!=0&&$monLieuArrivee!=''&&$monLieuDépart!=''&&$monIdentifiantIsCertified==true){ $onContinueLaProcedure=true;}
C'est du camélisé sans séparateur.
Mais cela peut également s'écrire :
if ( $date_arr != 0 && $date_dep != 0 && $lieu_arr != '' && $lieu_dep != '' && $id_cert == true ) { $continue = true; }
pour une meilleure lisibilité.
Le programmeur qui écrira ses scripts en omettant systématiquement les séparateurs (peut-être afin de gagner le temps en ne frappant pas la barre d'espace ?) fera toujours perdre du temps, et sera la cause de probables erreurs d'interprétation (éventuellement pour lui-même dans l'avenir), car il aura écrit de l'illisible en mode de « lecture naturelle » : il imposera à tout lecteur un effort supplémentaire à celui de la seule lecture, afin que le lecteur trouve la place que devraient avoir les séparateurs pour reconstituer correctement les mots, et finalement accéder au sens du texte.
Par ailleurs notons une différence entre « $maDateArrivee, $maDateDepart » et « $date_arr, $date_dep » : vous aurez noté que le « ma » a disparu de la dernière formulation.
Je ne sais d'où vient ce « ma », « mon », « mes » devant un certain nombre de variables utilisées ici ou là, mais il est strictement inutile car sans signification et ajoute de la surcharge inutile.
C'est ce que l'on retrouve dans les dossiers de systèmes d'exploitation et n'a absolument aucun sens.
Qu'un dossier sur un ordinateur s'appelle « Mes documents » ne signifie pas que celui qui accédera à ce dossier le possède réellement...
Bien des informaticiens semblent ignorer que « Le moi est haïssable » (Pascal)...
A lire : « Les geeks sont-ils anti “intellectuels”? »


Commentaires
Aucun commentaire pour le moment.
Ajouter un commentaire