Combien de parameters sont trop nombreux?

Les routines peuvent avoir des parameters, ce n’est pas une nouvelle. Vous pouvez définir autant de parameters que nécessaire, mais trop d’entre eux rendront votre routine difficile à comprendre et à gérer.

Bien sûr, vous pouvez utiliser une variable structurée comme solution de contournement: mettre toutes ces variables dans une seule structure et les transmettre à la routine. En fait, l’utilisation de structures pour simplifier les listes de parameters est l’une des techniques décrites par Steve McConnell dans Code Complete . Mais comme il dit:

Les programmeurs attentifs évitent de regrouper les données plus que ce qui est logiquement nécessaire.

Donc, si votre routine a trop de parameters ou si vous utilisez une structure pour masquer une grande liste de parameters, vous faites probablement quelque chose de mal. C’est-à-dire que vous ne gardez pas le couplage libre.

Ma question est la suivante: quand puis-je considérer une liste de parameters trop grande? Je pense que plus de 5 parameters sont trop nombreux. Qu’est-ce que tu penses?

Quand quelque chose de si obscène est-il considéré comme pouvant être réglé malgré la garantie du 1er amendement à la liberté d’expression? Selon le juge Potter Stewart, “je le sais quand je le vois”. La même chose vaut ici.

Je déteste faire des règles ssortingctes comme celle-ci car la réponse change non seulement en fonction de la taille et de la scope de votre projet, mais je pense que cela change même au niveau du module. Selon ce que votre méthode est en train de faire ou ce que la classe est censée représenter, il est fort possible que 2 arguments soient trop nombreux et constituent un symptôme de trop de couplage.

Je suggère que, en posant la question en premier lieu, et en qualifiant votre question autant que vous l’avez fait, vous savez vraiment tout cela. La meilleure solution est de ne pas compter sur un nombre de participants difficile et rapide, mais plutôt d’examiner les revues de conception et les revues de code parmi vos pairs pour identifier les domaines dans lesquels vous avez peu de cohésion et un couplage étroit.

N’ayez jamais peur de montrer votre travail à vos collègues. Si vous avez peur, c’est probablement le plus grand signe que quelque chose ne va pas avec votre code et que vous le savez déjà .

Une fonction ne peut avoir que trop de parameters si certains parameters sont redondants. Si tous les parameters sont utilisés, la fonction doit avoir le nombre correct de parameters. Prenez cette fonction souvent utilisée:

HWND CreateWindowEx ( DWORD dwExStyle, LPCTSTR lpClassName, LPCTSTR lpWindowName, DWORD dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam ); 

Cela fait 12 parameters (9 si vous regroupez les x, y, w et h en rectangle) et il y a aussi les parameters dérivés du nom de la classe. Comment pourriez-vous réduire cela? Voulez-vous réduire le nombre plus au point?

Ne laissez pas le nombre de parameters vous déranger, assurez-vous simplement que c’est logique et bien documenté et laissez intellisense * vous aider.

* D’autres assistants de codage sont disponibles!

Dans le code propre , Robert C. Martin a consacré quatre pages au sujet. Voici l’essentiel:

Le nombre idéal d’arguments pour une fonction est zéro (niladique). Vient ensuite l’un (monadique), suivi de près par deux (dyadique). Trois arguments (sortingadiques) doivent être évités autant que possible. Plus de trois (polyadiques) nécessitent une justification très particulière – et ne devraient pas être utilisés de toute façon.

Certains codes avec lesquels j’ai travaillé par le passé utilisaient des variables globales simplement pour éviter de faire passer trop de parameters.

S’il vous plaît ne faites pas ça!

(Habituellement.)

Si vous commencez à compter mentalement les parameters dans la signature et à les faire correspondre à l’appel, il est temps de refactoriser!

Merci beaucoup pour toutes vos réponses:

  • C’était un peu surprenant de trouver des gens qui pensent aussi (comme moi) que 5 parameters est une bonne limite pour la santé mentale du code.

  • Généralement, les gens ont tendance à convenir qu’une limite entre 3 et 4 est une bonne règle. Ceci est raisonnable car les gens ont généralement du mal à compter plus de 4 choses.

  • Comme le souligne Milan , les gens peuvent en moyenne garder plus ou moins 7 choses dans leur tête à la fois. Mais je pense que vous ne pouvez pas oublier que lorsque vous concevez / maintenez / étudiez une routine, vous devez garder à l’esprit plus de choses que les parameters.

  • Certaines personnes considèrent qu’une routine doit comporter autant d’arguments que nécessaire. Je suis d’accord, mais seulement pour quelques cas spécifiques (appels aux API OS, routines où l’optimisation est importante, etc.). Je suggère de masquer la complexité de ces routines en ajoutant une couche d’abstraction juste au-dessus de ces appels lorsque cela est possible.

  • Nick a quelques reflections intéressantes à ce sujet. Si vous ne voulez pas lire ses commentaires, je résume pour vous: en bref, cela dépend :

    Je déteste faire des règles ssortingctes comme celle-ci car la réponse change non seulement en fonction de la taille et de la scope de votre projet, mais je pense que cela change même au niveau du module. Selon ce que votre méthode est en train de faire ou ce que la classe est censée représenter, il est fort possible que 2 arguments soient trop nombreux et constituent un symptôme de trop de couplage.

    La morale ici est de ne pas avoir peur de montrer votre code à vos pairs, de discuter avec eux et d’essayer “d’identifier les domaines dans lesquels vous avez peu de cohésion et un lien étroit” .

  • Enfin, je pense que beaucoup d’accord avec Nick, et conclut sa consortingbution satirique avec cette vision poétique (voir les commentaires ci-dessous) de l’art de la programmation:

    La programmation n’est pas une ingénierie. L’organisation du code est un art car il dépend de facteurs humains, qui dépendent trop du contexte pour toute règle ssortingcte.

Cette réponse suppose un langage OO. Si vous n’utilisez pas un, ignorez cette réponse (ce n’est pas une réponse tout à fait différente de la langue.

Si vous transmettez plus de 3 parameters (en particulier des types / objects insortingnsèques), ce n’est pas que ce soit “Trop”, mais vous risquez de ne pas pouvoir créer un nouvel object.

Recherchez des groupes de parameters qui sont passés dans plus d’une méthode – même un groupe passé en deux méthodes garantit presque la présence d’un nouvel object.

Ensuite, vous réorganisez les fonctionnalités dans votre nouvel object et vous ne croirez pas à quel point cela aide à la fois votre code et votre compréhension de la programmation OO.

Il semble qu’il y ait d’autres considérations que le simple nombre, en voici quelques-unes qui me viennent à l’esprit:

  1. relation logique avec l’objective principal de la fonction par rapport aux parameters uniques

  2. S’ils ne sont que des drapeaux d’environnement, le regroupement peut être très pratique

L’un des épigrammes de programmation bien connus d’Alan Perlis (relaté dans ACM SIGPLAN Notices 17 (9), septembre 1982) stipule que “Si vous avez une procédure avec 10 parameters, vous en avez probablement manqué”.

Selon Steve McConnell dans Code Complete , vous devriez

Limiter le nombre de parameters d’une routine à environ sept

Pour moi, lorsque la liste croise une ligne sur mon IDE, alors c’est un paramètre de trop. Je veux voir tous les parameters sur une seule ligne sans rompre le contact visuel. Mais c’est juste ma préférence personnelle.

Je suis généralement d’accord avec 5, cependant, s’il y a une situation où j’ai besoin de plus et que c’est la manière la plus claire de résoudre le problème, alors j’utiliserais plus.

Sept choses dans la mémoire à court terme?

  1. Nom de la fonction
  2. Valeur de retour de la fonction
  3. But de la fonction
  4. Paramètre 1
  5. Paramètre 2
  6. Paramètre 3
  7. Paramètre 4

Dans Worst 5 Code Snippets , cochez la deuxième, “Est-ce un constructeur”. Il a comme plus de 37 ⋅ 4 ≈ 150 parameters:

Ici, un programmeur a écrit à ce constructeur que certains d’entre vous pensent que c’est un gros constructeur, mais il a utilisé les outils de génération automatique de code eclipse [.] NOO, dans ce constructeur il y avait un petit bogue que j’ai découvert. conclure que ce constructeur a été écrit à la main. (au fait, ce n’est que la partie supérieure du constructeur, ce n’est pas complet).

constructeur avec plus de 150 paramètres

Un plus que nécessaire. Je ne veux pas être désinvolte, mais il y a certaines fonctions qui nécessitent nécessairement plusieurs options. Par exemple:

 void * mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t offset); 

Il y a 6 arguments et chacun d’entre eux est essentiel. De plus, il n’y a pas de lien commun entre eux pour justifier leur regroupement. Vous pourriez peut-être définir “struct mmapargs”, mais cela serait pire.

Je définirais la limite pour les fonctions publiques à 5 parameters moi-même.

À mon humble avis, les longues listes de parameters ne sont acceptables que dans les fonctions d’assistance privées / locales qui ne sont censées être appelées qu’à partir de quelques endroits spécifiques du code. Dans ces cas, vous devrez peut-être transmettre beaucoup d’informations d’état, mais la lisibilité n’est pas une préoccupation majeure puisque vous (ou quelqu’un qui maintiendra votre code et devez comprendre les principes fondamentaux de votre module) devez vous soucier de appeler cette fonction.

Une question connexe que vous devriez considérer est la cohérence de la routine. Un grand nombre de parameters peut être une odeur qui vous dit que la routine elle-même essaie de faire trop et que sa cohésion est donc suspecte. Je suis d’accord pour dire qu’un nombre de parameters difficile et rapide est probablement impossible, mais je suppose qu’une routine de grande cohésion impliquerait un faible nombre de parameters.

97 sonne juste comme il faut.

De toute façon, vous perdez de la flexibilité.

Selon Perl Best Practices , 3 est acceptable, 4 est trop. C’est juste une directive, mais dans notre magasin, c’est ce que nous essayons de respecter.

Je m’arrête à trois parameters en règle générale. De plus, il est temps de passer un tableau de parameters ou un object de configuration à la place, ce qui permet également d’append de futurs parameters sans modifier l’API.

Une ressortingction de longueur sur une liste de parameters n’est qu’une ressortingction de plus. Et la ressortingction signifie la violence appliquée. Cela semble drôle, mais vous pouvez être non violent même en programmant. Laissez simplement le code dicter les règles. Il est évident que si vous avez beaucoup de parameters, le corps de la méthode fonction / classe sera assez grand pour les utiliser. Et les extraits de code en gros peuvent généralement être refactorisés et divisés en morceaux plus petits. Ainsi, vous obtenez une solution contre le fait de disposer de nombreux parameters en tant que bonus gratuit, car ils sont répartis entre les plus petites parties de code modifiées.

Une chose que je voudrais souligner du sharepoint vue des performances est que, en fonction de la manière dont vous transmettez les parameters à une méthode, le passage de nombreux parameters ralentira le programme car chaque paramètre doit être copié puis placé dans la stack.

Utiliser une seule classe pour englober tous les parameters fonctionnerait mieux car un seul paramètre transmis par référence serait élégant et plus rapide, et plus rapide!

Selon moi, il pourrait y avoir des cas où vous dépasserez 4 ou un nombre fixe. Les choses à surveiller pourraient être

  1. Votre méthode en fait trop et vous devez refactoriser.
  2. Vous pouvez envisager d’utiliser une collection ou une structure de données.
  3. Repenser la conception de votre classe, peut-être que certaines choses ne doivent pas être transmises.

Du sharepoint vue de la facilité d’utilisation ou de la facilité de lecture du code, je pense que lorsque vous avez besoin de «boucler» votre signature de méthode, cela devrait vous faire réfléchir. pas de résultat. Certaines très bonnes bibliothèques, passées et présentes, utilisent plus de 4 ou 5 poussettes.

Ma règle de base est que je dois être capable de mémoriser les parameters suffisamment longtemps pour pouvoir regarder un appel et dire ce qu’il fait. Donc, si je ne peux pas regarder la méthode, puis passer à un appel de méthode et me rappeler quel paramètre fait quoi, alors il y en a trop.

Pour moi, cela équivaut à environ 5, mais je ne suis pas si shiny. Votre kilométrage peut varier.

Vous pouvez créer un object avec des propriétés pour contenir les parameters et les transmettre si vous dépassez la limite définie. Voir le livre de Martin Fowler sur le refactoring et le chapitre sur la simplification des appels de méthode.

Cela dépend fortement de l’environnement dans lequel vous travaillez. Prenez par exemple le javascript. En javascript, le meilleur moyen de transmettre des parameters consiste à utiliser des objects avec des paires clé / valeur, ce qui dans la pratique signifie que vous n’avez qu’un seul paramètre. Dans d’autres systèmes, l’attraction sera à trois ou quatre.

En fin de compte, tout se résume à des goûts personnels.

Je suis d’accord avec 3 est d’accord, 4 est trop comme guide. Avec plus de 3 parameters, vous faites inévitablement plus d’une tâche. Plus d’une tâche doit être divisée en plusieurs méthodes.

Cependant, si je regardais le dernier projet sur lequel j’ai travaillé, les exceptions seraient nombreuses et la plupart des cas seraient difficiles à définir à 3 parameters.

Si j’ai 7 à 10 parameters dans une routine, je cherche à les regrouper dans une nouvelle classe, mais pas si cette classe n’est rien d’autre qu’un groupe de champs avec des getters et des setters. La nouvelle classe doit faire autre chose que en dehors. Sinon, je préfère utiliser la longue liste de parameters.

C’est un fait connu, en moyenne, les gens peuvent garder 7 +/- 2 choses dans leur tête à la fois. J’aime utiliser ce principe avec des parameters. En supposant que les programmeurs sont tous des gens intelligents au-dessus de la moyenne, je dirais que tout ce qui est 10+ est trop.

BTW, si les parameters sont similaires en aucune façon, je les mettrais dans un vecteur ou une liste plutôt qu’une structure ou une classe.

Je baserais ma réponse sur la fréquence à laquelle la fonction est appelée.

S’il s’agit d’une fonction d’initialisation qui n’est appelée qu’une seule fois, laissez-la prendre 10 ms ou plus, peu importe.

Si on l’appelle un tas de fois par image, j’ai tendance à créer une structure et à y passer un pointeur, car cela tend à être plus rapide (en supposant que vous ne reconstruisez pas la structure à chaque fois).

Selon Jeff Bezos de la renommée amazonienne, pas plus que peut être nourri avec deux pizzas :