Dans le domaine de la programmation fonctionnelle, lâimmutabilitĂ© des donnĂ©es est un des concepts les plus importants mais aussi un des plus durs Ă assimiler. Il est beaucoup plus simple de travailler avec des objets mutables et dans la grande majoritĂ© des cas le code nâen est pas affectĂ©. Alors prĂ©fĂ©rer lâimmutabilitĂ© des donnĂ©es dans son application web, ça peut sembler sâinfliger des contraintes supplĂ©mentaires sans fondement, pourtant ça ne viendrait pas Ă lâidĂ©e dâun collĂ©gien de faire ses exercices dans son manuel empruntĂ© au CDI. Traiter toutes ses donnĂ©es comme un livre empruntĂ©, câest garantir que tous les lecteurs accĂšdent aux donnĂ©es non corrompues. Dans cet article, on va expliquer la diffĂ©rence entre les donnĂ©es mutables et immutables, ce que cela implique dans votre code javascript et appliquer les bonnes pratiques de manipulation de donnĂ©es.
Le cas des variables mutables
En javascript, seuls les objets sont mutables. Mais si vous avez dĂ©jĂ entendu que tout est objet en javascript alors câest perdu, tout serait donc mutable ? La rĂ©alitĂ© est un peu plus complexes que ça. En effet, il existe 7 types primitifs immutables, parmi eux : string, number, boolean, undefined, etc. Mais il existe un objet wrapper autour de chaque type primitif. Donc en principe, tout ce avec quoi on interagit quand on Ă©crit du code javascript est mutable.
Mais in fine, ça veut dire quoi (im)mutable ? On dira quâune valeur est immutable si pour lâĂ©diter on doit recrĂ©er une valeur. Ouvrez la console et essayez le code suivant, la chaine de caractĂšre associĂ©e ne sera pas Ă©ditĂ©e :
const foo = "Coucou le monde!";
foo[1] = "s";
console.log(foo) // output: "Coucou le monde!"
â ïž Dans le cas de mutabilitĂ©, on parle de la valeur (dans lâexemple : "Coucou le monde!") et pas de la variable (dans lâexemple : foo) associĂ©e. La variable peut donc changer autant de fois de valeur, cela ne qualifiera pour autant pas le caractĂšre mutable de ces valeurs. â ïž
Inversement, pour une liste, on peut modifier nâimporte quel Ă©lĂ©ment, en ajouter et en enlever sans recrĂ©er une liste Ă chaque fois.
Les mots clefs const
et readonly
nâont rien Ă voir avec la mutabilitĂ© des valeurs. Ils garantissent juste que lâon ne peut rĂ©assigner de valeurs. On n'en parlera donc pas.
En pratique, les valeurs mutables que lâon utilise sont les objets et les listes.
âčïž On parlera de mĂ©thode mutable si la mĂ©thode modifie la valeur de lâobjet sur laquelle elle sâapplique. Inversement, un mĂ©thode immutable crĂ©era une nouvelle rĂ©fĂ©rence avec les nouvelles valeurs. En pratique, on parle de fonction pure.âčïž
Pourquoi travailler avec des données immutables ?
Maintenant quâon a vu la diffĂ©rence entre valeur mutable et valeur immutable, on va donner deux exemples en Angular pour saisir lâimpact que la mutabilitĂ© des valeurs peut avoir sur le rĂ©sultat de notre code.
ChangeDetector dâAngular
Dans cet exemple de code, on veut crĂ©er une animation dans laquelle chaque Ă©lĂ©ment de la liste sâaffiche aprĂšs chaque seconde. Mais pourquoi lâanimation du haut ne se met pas Ă jour ? La diffĂ©rence se situe sur les mĂ©thodes pour mettre Ă jour notre liste.
Le changeDetector dâAngular ne dĂ©tecte pas les mutations de valeur. Donc si on ne crĂ©e pas une nouvelle valeur, le composant (OnPush) ou le pipe (pure) ne mettra pas Ă jour la valeur dans la vue, mĂȘme si les valeurs sont correctes.
Il faut bien comprendre que dans les deux cas la liste est bel et bien mise Ă jour, mais Angular ne peut dĂ©tecter ces changements car pour lui la liste mutĂ©e est la mĂȘme.
âčïž Muter (= modifier une liste de maniĂšre mutable) une liste câest lui ajouter, enlever ou modifier un ou plusieurs Ă©lĂ©ment. On ne peut pas changer une liste de maniĂšre immutable, il faut la recrĂ©er.âčïž
Partage de valeur
Dans ce deuxiĂšme exemple, nous avons deux composants qui partagent un objet configuration. On change sa propriĂ©tĂ© color parce quâĂ la place dâune valeur hexadĂ©cimale, on veut une valeur RGB pour le CSS. Malheureusement, si je change la valeur pour lâun, la valeur change pour les deux.
Pour répondre au problÚme, on peut appliquer nos changement à la liste de maniÚre immutable. On verra dans la partie suivante comment faire dans le cas général en Javascript.
Ces problĂ©matiques ne sont pas propres Ă Angular, ni mĂȘme au code Javascript mais quand on manipule beaucoup de donnĂ©es, on a intĂ©rĂȘt Ă appliquer des changements immutables aux valeurs que lâon manipule. Ces deux exemples sont simples puisquâil n'y a que deux-trois composants mais quand les donnĂ©es ont des parcours plus complexes, ce sont gĂ©nĂ©ralement des bugs trĂšs difficiles Ă dĂ©celer.
Fake it till you make it
Comment travailler avec des données mutables ? Faßtes semblant que les données soient immutables. Ainsi, à chaque update de valeur, il faut recréer son objet.
Le problĂšme de cette mĂ©thode câest quâelle nĂ©cessite de bien connaĂźtre les mĂ©thodes mutables associĂ©es Ă son objet. Pour les objets issus de librairies, bon courage car il faudra tester Ă la main. Pour les objets natifs comme Array, MDN saura vous rĂ©pondre.
Vous pouvez dÚs à présent bannir sort
et accueillir sa petite sĆur mutable toSorted
tout frais du standard 2023 dâEcmaScript (cf.NouveautĂ©s 2023 JS). Plus simplement, toutes les mĂ©thodes qui sâĂ©crivent sous la forme newValue = oldValue.method()
ont de bonnes chances dâĂȘtre immutables.
âčïž Pour aller plus loin, il existe des librairies JS (immutable& immer) qui implĂ©mentent diverses structures de donnĂ©es immutables pour remplacer les objets natifs javascript mutables. Ces structures de donnĂ©es sont plus sĂ»res Ă utiliser mais nĂ©cessitent que les dĂ©veloppeurs soient formĂ©s sur ces librairies. Leur grand intĂ©rĂȘt est surtout au niveau des performances.âčïž
Conclusion
Comme le prĂ©cise la documentation MDN au sujet de lâimmutabilitĂ©, il est dur de travailler quâavec des structures de donnĂ©es immutables si aucune sĂ©mantique de langage ne le garantit (Rappel, le mot clef const ne garantit pas lâimmutabilitĂ© des donnĂ©es, seulement de la variable).
Dans le cas de Javascript, cela est avant tout un contrat entre développeurs que les mutations ne sont pas de bons pattern de développement (Par exemple en utilisant Object.freeze ou des librairies spécialisées).
Comme on lâa vu dans la partie dâexemple, le grand intĂ©rĂȘt de lâimmutabilitĂ© est dâĂ©viter des bugs oĂč les mutations ne se transposent pas sur lĂ oĂč on les fait, ou pire quâelles se transposent lĂ oĂč on ne les fait pas.
Enfin, lâimmutabilitĂ© est lâun des principes clefs de la programmation fonctionnelle et ouvre les portes aux fonctions pures.
TL;DR: Avoid in place mutation, prefer replacing
Source
JavaScript data types and data structures - JavaScript | MDN
Immutable - MDN Web Docs Glossary: Definitions of Web-related terms | MDN
How everything is Object in JavaScript ?
Prototype and Protypal Inheritance in JavaScript
Primitive - MDN Web Docs Glossary: Definitions of Web-related terms | MDN
Immutability
How is almost everything in Javascript an object?
Top comments (0)