[1/3] 3 acronymes que TOUS les développeurs devraient connaître : DRY
Don't Repeat Yourself. Probablement plus subtile que ce que vous imaginez !
Cet article fait partie d’un groupe d’articles à propos des 3 acronymes que TOUS les développeurs devraient connaitre. C’est le premier article de la série :) Bonne lecture !
Dans l’article de la semaine dernière, nous avons vu l’acronyme SOLID.
Nous allons maintenant aborder trois autres acronymes qui revêtent une importance capitale dans la façon dont nous développons nos applications.
Commençons donc cette semaine par l’acronyme DRY !
Let’s go 💪
DRY : Dont’ Repeat Yourself
Le principe de cet acronyme est très simple : ne pas se répéter dans le code. Autrement dit, éviter de dupliquer du code un peu partout dans notre codebase.
Mais d’ailleurs, pourquoi est-ce qu’il ne faut pas dupliquer notre code ? Et puis, à quel moment peut-on considérer que du code est vraiment dupliqué ?
Voyons ça :
Pourquoi éviter les duplications
Imaginez que vous deviez préparer une soirée d’anniversaire à un ami 🥳.
Vous devez donc prévenir chaque invité de la date et de l’heure de la soirée.
Vous envoyez donc un message à chacun des invités, séparément :
📲 “Hello ! Alors pour la soirée, ce sera le 10 juin à 20h :)” - Envoyé à Marion.
📲 “Hello ! Alors pour la soirée, ce sera le 10 juin à 20h :)” - Envoyé à Tristan.
📲 “Hello ! Alors pour la soirée, ce sera le 10 juin à 20h :)” - Envoyé à Camille.
📲 “Hello ! Alors pour la soirée, ce sera le 10 juin à 20h :)” - Envoyé à Marie.
Un petit copié-collé et c’est plié !
Vous vous rendez-compte que vous avez oublié Arnaud, votre cousin, vous lui envoyer donc le même message copié-collé :
📲 “Hello ! Alors pour la soirée, ce sera le 10 juin à 20h :)” - Envoyé à Arnaud.
Les jours passent et un changement de dernière minute s’opère ! L’horaire est modifié. Ni une ni deux vous décidez donc de renvoyer un message aux invités :
📲 “Hello ! Dernière minute, la soirée est décalée à 19h !” - Envoyé à Marion.
📲 “Hello ! Dernière minute, la soirée est décalée à 19h !” - Envoyé à Arnaud.
📲 “Hello ! Dernière minute, la soirée est décalée à 19h !” - Envoyé à Camille.
📲 “Hello ! Dernière minute, la soirée est décalée à 19h !” - Envoyé à Marie.
Votre œil aguerri a-t-il détecté le problème ?
Tristan n’a pas été prévenu du changement d’horaire !
Quand on fait des copier-coller à tout va, on prend le risque d’oublier certains cas ! Ici la responsabilité de prévenir tous les invités nous incombe personnellement.
Bien sûr, la solution ici aurait été de tout simplement créer un groupe WhatsApp par exemple.
La responsabilité de prévenir tous les invités aurait été déplacée au groupe lui-même, vous n’auriez pas eu à vous soucier d’à qui vous avez envoyé ou non le message.
C’est la même chose pour le code ! Quand on se retrouve à faire beaucoup de copier-coller et que l’on doit changer chacun de ses “collages” en même temps à chaque fois, c’est le signe évident d’une duplication à corriger.
Prenons un exemple simple :
Ce code propose donc trois petites fonctions dont le seul but, discutable, est d’afficher dans la console des informations liées à une personne.
On remarque ici que le ${person.firstName}
a donc été copié-collé dans chaque fonction pour afficher le nom de la personne.
Que se passe-t-il si l’on décide d’inclure le nom de famille ?
Nous sommes obligés de penser à rajouter le ${person.lastName}
dans chaque fonction ! J’insiste sur le “obligés de penser”, car cela traduit que la responsabilité d’afficher la personne nous incombe personnellement en tant que développeur ! C’est quand même un comble…
D’ailleurs, les plus attentifs d’entre vous aurons remarqués qu’une coquille s’est glissée dans la dernière fonction ! J’ai écrit ${person.lastname}
au lieu de ${person.lastName}
(il manquait la majuscule).
Ces erreurs sont liées à de l’inattention, et devinez qui est extrêmement propice à faire des fautes d’inattention ? Nous, pauvres humains… Et devinez qui ne peut absolument jamais faire de faute d’inattention ? L’ordinateur :)
On doit donc lui déléguer la responsabilité d’afficher une personne, pour que nous n’ayons plus à y penser nous-même !
Ces duplications ont mis en évidence un concept qui n’était visible que par nos yeux d’humains, mais invisible pour l’ordinateur : le nom complet d’une personne.
Il nous faut donc créer ce concept de “nom complet” dans le code, afin que l’ordinateur puisse l’utiliser :
En créant la fonction getPersonFullName
nous avons donc englobé le concept de nom complet. Ce faisant, nous avons créé une abstraction. Plus précisément, nous avons “abstrait” le concept de “nom complet” du concept de “personne”.
C’est un mécanisme fondamental en programmation !
Mais attention de ne pas tomber dans certains pièges…
Les pièges à éviter
Reprenons notre exemple du groupe WhatsApp. Pour rappel, Marion, Camille, Arnaud, Tristan et Marie s’y trouvent.
Content de pouvoir enfin sortir un peu de chez vous après ce confinement, vous décidez d’organiser une nouvelle soirée ! Cette fois-ci, vous invitez Marion, Camille, Arnaud, mais pas Tristan ni Marie. De plus, vous invitez Benoît et Estelle, qui n’étaient pas invités à la première soirée.
Naturellement, vous allez donc créer un second groupe, propre à cette seconde soirée, dans lequel vous inviterez tous les participants.
Mais du coup vous avez dupliqué une partie du groupe initial dans un autre groupe !
Oui, et vous avez bien fait :)
Il aurait été idiot d’inviter dans le groupe de la première soirée Benoît et Estelle pourtant conviés qu’à la deuxième. Les conversations se seraient croisées, et ça aurait vite été un beau bazar…
C’est ici une “duplication” qui n’en est en fait pas une ! Car les deux groupes ont tous les deux une raison différente d’être “modifié”, chacun en rapport avec sa soirée.
C’est encore une fois la même chose dans le code ! Essayons de voir dans l’exemple précédent une “fausse” duplication. On s’aperçoit notamment que dans les fonctions logPersonAddress
et logPersonWork
on utilise à chaque fois une petite phrase après l’affichage du nom, on met ensuite les deux points, puis on affiche la propriété qui nous intéresse (l’adresse ou le travail).
On pourrait être tenté de reproduire le même procédé qu’avec le nom complet en créant une fonction getSentence()
par exemple :
Et voilà, le piège du DRY s’est refermé contre nous !
Ce code est plus difficile à comprendre, il augmente la charge mentale nécessaire à la compréhension globale du code.
Pour saisir pourquoi, il faut comprendre que toute abstraction à un coût. En effet, chaque abstraction créer ce que l’on appelle un niveau d’indirection supplémentaire. Si avant il suffisait de lire la ligne pour comprendre directement ce que faisait le code, il faut maintenant se référer à une fonction située ailleurs dans le code pour tenter de comprendre.
Ce coût est largement compensé lorsque l’abstraction permet de rendre le code plus simple à comprendre, sans devoir rentrer dans les détails.
La différence entre l’abstraction du concept de “sentence” et celui de “nom complet” est que le concept de “sentence” n’a pas lieu d’exister dans le “domaine” de cette miniapplication.
En effet, nous traitons ici simplement des concepts liés à des informations sur des personnes.
Les concepts que l’on peut s’attendre à découvrir sont donc des abstractions “abstraites” du concept de “personne”.
Un “nom complet” est bien abstrait du concept de “personne”.
Une “sentence” n’est en rien relié à un concept de “personne”.
Nous avons donc ici une mauvaise abstraction, car son coût est est supérieur à son bénéfice apporté dans le code. Cette abstraction est même contre-productive, car elle complexifie inutilement le code.
Beaucoup de développeurs débutants ont tendance à vouloir toujours tout rendre “générique”, à supprimer le moindre embryon de duplication dans le code. Ce faisant, le code est saturé en abstractions inutiles et devient totalement illisible !
Il existe des astuces pour ne pas tomber dans ce piège :
Comment trouver les bonnes duplications et donc les bonnes abstractions ?
Il existe plusieurs astuces pour ne pas tomber dans le piège d’avoir de mauvaises abstractions.
ne pas hésiter à laisser les duplications au début le temps de voir apparaître les concepts…
…en vous autorisant à un copier-coller. Lorsque vous vous apercevez que vous devez en faire un deuxième et ainsi avoir trois fois le même code, c’est probablement l’indication qu’il existe une abstraction possible.
lorsque vous vous apercevez que vous devez toujours changer les mêmes bouts de code partout : c’est probablement qu’il existe un concept sous-jacent que vous n’avez pas explicitement nommé dans votre code
J’espère que ce petit exemple vous aura permis d’y voir plus clair sur l’intérêt de l’acronyme DRY !
Happy Coding :)
Cet article vous a plu ? Vous pouvez me soutenir gratuitement en vous inscrivant à mon programme de parrainage, en échange, je vous offre des bons de réduction valables à vie sur tous les cours (actuels et futurs) de CraftAcademy.fr 🎉