J'ai eu un petit débat en cours avec un collègue. Autrement dit, y a-t-il une bonne raison de cacher / encapsuler des fonctions qui sont pures?
Par "pur", je veux dire la définition de wikipedia :
- Renvoie toujours les mêmes résultats à partir de la même entrée. (Pour les besoins de cette discussion, il
Foo Create(){ return new Foo(); }
est considéré comme impur s'ilFoo
n'a pas de sémantique de valeur.) - N'utilise pas d'état mutable (sauf les variables locales) ou d'E / S.
- Ne produit pas d'effets secondaires.
design
pure-function
Telastyn
la source
la source
Réponses:
Une fonction pure pourrait encore être un détail d'implémentation. Bien que la fonction puisse ne causer aucun préjudice (du point de vue de ne pas rompre les invariants / contrats importants), en l'exposant, l'auteur et les utilisateurs de cette classe / module / package perdent. L'auteur perd parce qu'il ne peut plus le supprimer même si l'implémentation change et que la fonction ne lui est plus utile. Les utilisateurs perdent parce qu'ils doivent passer au crible et ignorer les fonctions supplémentaires qui ne sont pas pertinentes pour utiliser l'API afin de le comprendre.
la source
La question est à l'envers.
Vous ne cherchez pas de raison de rendre une fonction non publique. C'est un état d'esprit incorrect pour commencer (à mon avis). Le raisonnement devrait aller dans l'autre sens.
En d'autres termes - ne demandez pas "pourquoi devrais-je le rendre privé?". Demandez: "pourquoi devrais-je le rendre public?"
En cas de doute, ne l'exposez pas. C'est un peu comme le rasoir d'Ockham - ne multipliez pas les droits au-delà de la nécessité.
EDIT: Aborder les contre-arguments soulevés par @Telastyn dans les commentaires (pour éviter une discussion approfondie là-bas):
Oui, c'est parfois un problème si une classe est ouverte à l'héritage, mais vous ne pouvez pas remplacer certaines méthodes privées (dont vous souhaitez modifier le comportement).
Mais
protected
cela suffirait - et ce n'est toujours pas public.Si cela devient problématique, rendez-le simplement public! Il y a la nécessité dont je parlais :)
Mon point est que vous ne devriez pas le faire au cas où (YAGNI et tout).
Notez qu'il est toujours plus facile de rendre publique une fonction privée que de la ramener à la confidentialité. Ce dernier est susceptible de casser le code existant.
la source
Je ne pense pas que la décision de cacher / encapsuler une fonction devrait dépendre de sa pureté. Ce n'est pas parce qu'une fonction est pure que les externes doivent en être informés. Il est intéressant de noter que si la fonction est pure et destinée à être publique, elle n'a peut-être même pas besoin d'être un membre d'instance de l'interface, peut-être qu'elle est mieux adaptée en tant que statique. Mais encore une fois, tout cela dépend de l'intention du contrat et, dans ce cas, du regroupement logique des fonctionnalités et non de la pureté de la fonction.
la source
Les classes doivent adhérer au principe de responsabilité unique . Alors qu'une classe peut avoir besoin d'appeler d'autres fonctionnalités pour atteindre ses objectifs, elle ne doit exposer que les fonctions qui font partie de sa seule responsabilité.
Voici juste un exemple de cas où la visibilité pourrait causer un problème.
Considérez une classe qui frobnicate les widgets. Peut-être que dans le cadre de son code de frobnication, il a besoin d'une fonction utilitaire qui analyse une chaîne: il doit peut-être transformer le nom du widget d'une manière que les fonctions de chaîne standard ne prennent pas en charge.
Comme il s'agit d'une fonction pure (une chaîne entre, la transforme en quelque sorte, retourne une nouvelle chaîne), elle peut être publique ou privée sans conséquence. Ou est-ce possible?
Si vous le rendez public, votre classe a maintenant deux responsabilités: frobnicating widgets et transforming strings. Cela viole SRP et peut provoquer des problèmes si d'autres classes dépendent de la fonction. Comme vous pensez que c'est quelque chose qui n'est utilisé qu'en interne à la classe, vous pouvez peut-être changer son interface ou sa visibilité. Désormais, les classes des autres parties du système sont interrompues.
En gardant la fonction privée, personne n'a jamais la possibilité de s'appuyer sur du code qui ne fait pas partie de la responsabilité unique de la classe.
la source
StringTransformer
classe distincte pour encapsuler deux ou trois lignes de code qui ne sont utilisées qu'à un seul endroit? Je suis d'accord qu'une fois le code utilisé à plusieurs endroits, il est préférable de le séparer en une nouvelle classe avec une seule responsabilité, mais il y a un compromis.