Dans Clean Code, il est écrit que "le nombre idéal d'arguments pour une fonction est zéro". Les raisons sont expliquées et ont un sens. Ce que je recherche, ce sont des techniques pour refactoriser les méthodes avec 4 arguments ou plus pour résoudre ce problème.
Une façon est d'extraire les arguments dans une nouvelle classe, mais cela conduirait sûrement à une explosion de classes? Et ces classes sont susceptibles de se retrouver avec des noms qui violent certaines des règles de dénomination (se terminant par "Data" ou "Info", etc.)?
Une autre technique consiste à faire des variables utilisées par plusieurs fonctions une variable membre privée pour éviter de les transmettre, mais cela étend la portée de la variable, éventuellement de telle sorte qu'elle soit ouverte aux fonctions qui n'en ont pas réellement besoin.
Je cherche juste des moyens de minimiser les arguments de fonction, après avoir accepté les raisons pour lesquelles c'est une bonne idée de le faire.
la source
Réponses:
La chose la plus importante à retenir est que ce sont des lignes directrices, pas des règles.
Il y a des cas où une méthode doit simplement prendre un argument. Pensez à la
+
méthode des nombres, par exemple. Ou laadd
méthode pour une collection.En fait, on pourrait même dire que ce que cela signifie d'ajouter deux nombres dépend du contexte, par exemple dans ℤ
3 + 3 == 6
, mais dans ℤ | 53 + 3 == 2
, donc vraiment l'opérateur d'addition devrait être une méthode sur un objet de contexte qui prend deux arguments au lieu d'un méthode sur les nombres qui prend un argument.De même, une méthode pour comparer deux objets doit être soit une méthode d'un objet prenant l'autre comme argument, soit une méthode du contexte, prenant deux objets en argument, donc il n'a tout simplement pas de sens d'avoir une méthode de comparaison avec moins d'un argument.
Cela dit, deux choses peuvent être faites pour réduire le nombre d'arguments pour une méthode:
Point
objet, ou au lieu de transmettre un nom d'utilisateur et un e-mail, passez unIdCard
objet.)Si votre modèle de domaine comporte de nombreux types de choses, votre code se retrouvera avec de nombreux types d'objets différents. Il n'y a rien de mal à cela.
Si vous ne trouvez pas un nom correct, vous avez peut-être regroupé trop d'arguments ou trop peu. Donc, soit vous avez juste un fragment d'une classe, soit vous avez plus d'une classe.
Si vous avez un groupe de méthodes qui fonctionnent toutes sur les mêmes arguments, et un autre groupe de méthodes qui ne le font pas, elles appartiennent peut-être à différentes classes.
Notez combien de fois j'ai utilisé le mot «peut-être»? C'est pourquoi ce sont des lignes directrices, pas des règles. Peut-être que votre méthode avec 4 paramètres est parfaitement bien!
la source
add
fonction pour les nombres naturels et laadd
fonction pour l'anneau d'entiers mod n sont deux actions de fonctions différentes sur deux types différents. Je ne comprends pas non plus ce que vous entendez par «contexte».Notez que zéro argument n'implique pas d'effets secondaires, car votre objet est un argument implicite. Regardez le nombre de méthodes sans arité de la liste immuable de Scala , par exemple.
Une technique utile que j'appelle la technique de "focalisation de l'objectif". Lorsque vous effectuez la mise au point d'un objectif d'appareil photo, il est plus facile de voir le vrai point de mise au point si vous le prenez trop loin, puis de le reculer au bon point. Il en va de même pour le refactoring logiciel.
Surtout si vous utilisez le contrôle de version distribué, les modifications logicielles sont faciles à expérimenter, voyez si vous aimez leur apparence, et reculez si vous ne le faites pas, mais pour une raison quelconque, les gens semblent souvent réticents à le faire.
Dans le contexte de votre question actuelle, cela signifie écrire les versions zéro ou un argument, avec plusieurs fonctions séparées d'abord, puis il est relativement facile de voir quelles fonctions doivent être combinées pour plus de lisibilité.
Notez que l'auteur est également un ardent défenseur du développement piloté par les tests, qui a tendance à produire des fonctions de faible densité au début, car vous commencez avec vos cas de test triviaux.
la source
Une approche qui vise simplement (et naïvement - ou devrais-je même dire à l' aveuglette ) à réduire le nombre d'arguments aux fonctions est probablement fausse. Il n'y a absolument rien de mal avec les fonctions ayant un grand nombre d'arguments. S'ils sont requis par la logique, eh bien ils sont nécessaires ... Une longue liste de paramètres ne m'inquiète pas du tout - tant qu'elle est correctement formatée et commentée pour la lisibilité.
Dans le cas où tous ou un sous-ensemble d'arguments appartiennent à une entité logique unique et sont généralement transmis en groupes dans votre programme, il peut être judicieux de les regrouper dans un conteneur - généralement une structure ou un autre objet. Des exemples typiques peuvent être une sorte de type de données de message ou d' événement .
Vous pouvez facilement exagérer cette approche - une fois que vous constatez que l'emballage et le déballage de trucs vers et depuis de tels conteneurs de transport génèrent plus de surcharge que cela améliore la lisibilité, vous êtes probablement allé trop loin.
OTOH, de grandes listes de paramètres peuvent être un signe que votre programme n'est peut-être pas correctement structuré - peut-être la fonction qui nécessite un si grand nombre de paramètres essaie simplement d'en faire trop et devrait être divisée en plusieurs fonctions plus petites. Je préfère commencer ici que de m'inquiéter du nombre de paramètres.
la source
Il n'y a pas de moyen magique: vous devez maîtriser le domaine problématique pour découvrir la bonne architecture. C'est le seul moyen de refactoriser: maîtriser le domaine problématique. Plus de quatre paramètres est juste un pari sûr que votre architecture actuelle est défectueuse et erronée.
Les seules exceptions sont les compilateurs (métaprogrammes) et les simulations, où la limite est théoriquement 8, mais probablement seulement 5.
la source