J'ai une méthode qui prend 30 paramètres. J'ai pris les paramètres et les ai mis dans une classe, de sorte que je puisse passer un seul paramètre (la classe) dans la méthode. Dans le cas d'un refactoring, est-il parfaitement acceptable de passer un objet qui encapsule tous les paramètres, même si c'est tout ce qu'il contient ?
Réponses
Trop de publicités?C'est une excellente idée. C'est typiquement la façon dont les contrats de données sont réalisés dans WCF par exemple.
L'un des avantages de ce modèle est que si vous ajoutez un nouveau paramètre, le consommateur de la classe n'a pas besoin de changer juste pour ajouter le paramètre.
Comme le mentionne David Heffernan, cela peut aider à auto documenter le code :
FrobRequest frobRequest = new FrobRequest
{
FrobTarget = "Joe",
Url = new Uri("http://example.com"),
Count = 42,
};
FrobResult frobResult = Frob(frobRequest);
Si d'autres réponses soulignent à juste titre qu'il est préférable de passer une instance d'une classe plutôt que 30 paramètres, sachez qu'un grand nombre de paramètres peut être le symptôme d'un problème sous-jacent.
Par exemple, il arrive souvent que le nombre de paramètres des méthodes statiques augmente, parce qu'elles auraient dû être des méthodes d'instance depuis le début, et que vous transmettez beaucoup d'informations qui pourraient plus facilement être maintenues dans une instance de cette classe.
Sinon, cherchez des moyens de regrouper les paramètres dans des objets d'un niveau d'abstraction plus élevé. L'intégration d'un ensemble de paramètres sans rapport entre eux dans une seule classe est une solution de dernier recours.
Voir Combien de paramètres sont trop nombreux ? pour avoir d'autres idées à ce sujet.
C'est un bon début. Mais maintenant que vous avez cette nouvelle classe, pensez à tourner votre code à l'envers. Déplacez la méthode qui prend cette classe comme paramètre dans votre nouvelle classe (en passant bien sûr une instance de la classe originale comme paramètre). Vous avez maintenant une grosse méthode, seule dans une classe, et il sera plus facile de la diviser en méthodes plus petites, plus faciles à gérer et à tester. Certaines de ces méthodes peuvent retourner dans la classe d'origine, mais une bonne partie restera probablement dans votre nouvelle classe. Vous avez dépassé Introduire l'objet paramètre sur Remplacer la méthode par l'objet méthode .
Avoir une méthode avec trente paramètres est un signe assez fort que la méthode est trop longue et trop compliquée. Trop difficile à déboguer, trop difficile à tester. Vous devez donc faire quelque chose pour y remédier, et Introduire un objet paramètre est un bon point de départ.
Si le refactoring vers un Objet Paramètre n'est pas en soi une mauvaise idée, il ne doit pas être utilisé pour masquer le fait qu'une classe qui a besoin de 30 données provenant d'ailleurs peut toujours être une sorte d'odeur de code. Le refactoring Introduce Parameter Object devrait probablement être considéré comme une étape dans un processus de refactoring plus large plutôt que comme la fin de cette procédure.
L'une des préoccupations qu'il n'aborde pas vraiment est celle de l'envie des fonctionnalités. Le fait que la classe à laquelle on transmet l'objet paramètre s'intéresse tant aux données d'une autre classe n'indique-t-il pas que les méthodes qui opèrent sur ces données devraient peut-être être déplacées là où se trouvent les données ? Il est vraiment préférable d'identifier les groupes de méthodes et de données qui vont ensemble et de les regrouper en classes, ce qui augmente l'encapsulation et rend votre code plus flexible.
Après plusieurs itérations de séparation du comportement et des données sur lesquelles il fonctionne en unités distinctes, vous devriez constater que vous n'avez plus de classes avec un nombre énorme de dépendances, ce qui est toujours un meilleur résultat final car cela rend votre code plus souple.
C'est une excellente idée et une solution très courante au problème. Les méthodes comportant plus de 2 ou 3 paramètres deviennent exponentiellement plus difficiles à comprendre.
L'encapsulation de tout cela dans une seule classe rend le code beaucoup plus clair. Parce que vos propriétés ont des noms, vous pouvez écrire du code auto-documenté comme ceci :
params.height = 42;
params.width = 666;
obj.doSomething(params);
Naturellement, lorsque vous avez beaucoup de paramètres, l'alternative basée sur l'identification de la position est tout simplement horrible.
Un autre avantage est que l'ajout de paramètres supplémentaires au contrat d'interface peut se faire sans imposer de changements à tous les sites d'appel. Toutefois, cela n'est pas toujours aussi trivial qu'il y paraît. Si différents sites d'appel exigent des valeurs différentes pour le nouveau paramètre, il est plus difficile de les retrouver qu'avec l'approche basée sur les paramètres. Dans l'approche basée sur les paramètres, l'ajout d'un nouveau paramètre force une modification à chaque site d'appel pour fournir le nouveau paramètre et vous pouvez laisser le compilateur faire le travail de les trouver tous.