Pourquoi ne pas utiliser de “Setters”
🍿 Dans ma conférence sur comment sortir du Legacy, je dis sans explication qu’il ne faut pas utiliser des setters, que c’est le mal absolu.
❓Un collègue (qui se reconnaîtra) m’a donc posé la question sur slack.
Voici la réponse :
L’utilisation des Setters dans la conception logicielle est un sujet de débat. Dans de nombreux cas, il est préférable de ne pas utiliser de setters ou d’en limiter l’utilisation. Quelques raisons qui expliquent cette approche :
- Encapsulation et contrôle
L’objectif principal de l’encapsulation est de protéger l’état interne d’un objet et de limiter les modifications imprévisibles. Les setters exposent directement les champs internes, ce qui peut :
Permettre des modifications inappropriées ou non sécurisées.
Rendre l’objet vulnérable à des états invalides si aucune validation n’est effectuée dans le setter.
Solution : Utiliser des méthodes plus explicites commeaddProduct(Product $product)
oueditPrice()
qui reflètent clairement l’intention et permettent d’encapsuler la logique métier. - Respect du principe d’immuabilité
Les objets immuables (dont l’état ne change pas après leur création) facilitent le debug, les tests et les opérations concurrentes. Les setters cassent l’immuabilité en permettant de modifier l’état d’un objet après sa création.
Exemple : Dans un objet représentant une facture, changer accidentellement le montant total après sa validation pourrait introduire des erreurs. Si cet objet est immuable, de telles modifications ne sont pas possibles. - Clarté du flux métier
L’utilisation des setters peut rendre le flux métier moins clair. Par exemple, un objet configuré via une série de setters peut être dans un état incomplet ou incohérent avant que tous les setters ne soient appelés.
Solution : Favoriser les constructeurs statiques ou les pattern comme le Builder qui obligent à fournir tous les paramètres nécessaires à la création d’un objet valide. - Couplage réduit et flexibilité accrue
Les setters augmentent le couplage entre les classes, car chaque classe qui utilise le setter doit connaître l’implémentation interne de l’autre. Cela rend difficile le changement ou l’évolution de la classe sans casser les dépendances.
Solution : Utiliser des interfaces ou des méthodes abstraites pour interagir avec les objets, tout en gardant le contrôle sur leur état interne. - Soutien aux pratiques modernes de développement
Les méthodologies comme la programmation fonctionnelle ou les frameworks comme Symfony ou Spring favorisent des concepts tels que l’immuabilité ou l’injection de dépendances. Ces paradigmes fonctionnent mieux avec des objets ayant des états bien définis, sans nécessiter de setters.
Mais alors quand les setters sont-ils acceptables ?
Il existe des situations où les setters sont justifiés :
- Objets DTO (Data Transfer Objects) : Les DTO sont des objets simples utilisés pour transporter des données sans logique métier. Les setters y sont souvent acceptables.
- Tests ou Mocking : Les setters peuvent faciliter la configuration d’objets dans les tests.
Frameworks spécifiques : Certains frameworks (comme JavaBeans) requièrent des getters et setters pour fonctionner correctement.
En conclusion
Plutôt que de fournir des setters, privilégiez :
- Des constructeurs explicites pour définir l’état initial.
- Des méthodes métier pour modifier l’état avec validation et intention.
- L’immuabilité autant que possible.
- En suivant ces principes, votre code sera plus robuste, lisible, et maintenable.
Précision importante : N’ayant pas le temps de répondre dans l’immédiat j’ai demandé à ChatGPT et sa réponse est cet article 😆