c# - pattern - refactoring primitive obsession




Est-il correct d'avoir une classe avec juste des propriétés à des fins de refactoring? (8)

J'ai une méthode qui prend 30 paramètres. J'ai pris les paramètres et les ai placés dans une classe, de sorte que je pourrais juste passer un paramètre (la classe) dans la méthode. Est-ce parfaitement bien dans le cas du refactoring de passer dans un objet qui encapsule tous les paramètres même si c'est tout ce qu'il contient.


30 paramètres est un gâchis. Je pense que c'est bien plus joli d'avoir un cours avec les propriétés. Vous pouvez même créer plusieurs "classes de paramètres" pour des groupes de paramètres qui correspondent à la même catégorie.


Alors que d'autres réponses ici soulignent correctement que le passage d'une instance d'une classe est préférable à la transmission de 30 paramètres, sachez qu'un grand nombre de paramètres peut être le symptôme d'un problème sous-jacent.

Par exemple, plusieurs fois les méthodes statiques augmentent dans leur nombre de paramètres, car ils auraient dû être des méthodes d'instance tout le long, et vous transmettez beaucoup d'informations qui pourraient être plus facilement maintenues dans une instance de cette classe.

Vous pouvez également rechercher des moyens de regrouper les paramètres dans des objets d'un niveau d'abstraction supérieur. L'immersion d'un groupe de paramètres indépendants dans une seule classe est un OMI de dernier recours.

Voir Combien de paramètres sont trop nombreux? pour d'autres idées à ce sujet.


C'est un bon début. Mais maintenant que vous avez cette nouvelle classe, pensez à transformer votre code à l'envers. Déplacez la méthode qui prend cette classe en tant que paramètre dans votre nouvelle classe (bien sûr, en passant une instance de la classe d'origine en tant que paramètre). Maintenant, vous avez une grande méthode, seule dans une classe, et il sera plus facile de la démonter en méthodes plus petites, plus faciles à gérer et testables. Certaines de ces méthodes peuvent revenir à la classe d'origine, mais une partie équitable restera probablement dans votre nouvelle classe. Vous avez dépassé Introduire l'objet de paramètre sur Remplacer la méthode avec l'objet de 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 dur à tester. Donc, vous devriez faire quelque chose à ce sujet, et Introduire l'objet de paramètre est un bon endroit pour commencer.


C'est une bonne idée. C'est typiquement comment les contrats de données sont faits dans WCF par exemple.

Un avantage 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 à documenter le code:

FrobRequest frobRequest = new FrobRequest
{
    FrobTarget = "Joe",
    Url = new Uri("http://example.com"),
    Count = 42,
};
FrobResult frobResult = Frob(frobRequest);

Comme indiqué précédemment: c'est la bonne étape à faire, mais considérons les suivants également:

  • votre méthode peut être trop complexe (vous devriez envisager de la diviser en plusieurs méthodes, ou même la transformer en une classe séparée)
  • si vous créez la classe pour les paramètres, rendez-la immutable
  • Si la plupart des paramètres peuvent être NULL ou pourraient avoir une valeur par défaut, vous pouvez utiliser le pattern Builder pour votre classe.

Il peut être raisonnable d'utiliser une classe Plain Old Data si vous refactoring ou non. Je suis curieux de savoir pourquoi vous pensiez que ce ne serait peut-être pas le cas.


Peut-être que les paramètres optionnels et nommés de C # 4.0 sont une bonne alternative?

Quoi qu'il en soit, la méthode que vous décrivez peut également être utile pour l'abstraction du comportement des programmes. Par exemple, vous pouvez avoir une fonction standard SaveImage(ImageSaveParameters saveParams) dans une interface où ImageSaveParameters est également une interface et peut avoir des paramètres supplémentaires en fonction du format de l'image. Par exemple JpegSaveParameters a une Quality propriété tandis que PngSaveParameters a une propriété BitDepth .

C'est ainsi que la boîte de dialogue de sauvegarde de Paint.NET le fait donc c'est un exemple très réel.


Tellement de bonnes réponses ici. Je voudrais ajouter mes deux cents.

L'objet de paramètre est un bon début. Mais il y a plus à faire. Considérez ce qui suit (exemples de ruby):

/ 1 / Au lieu de simplement regrouper tous les paramètres, voir s'il peut y avoir un regroupement significatif de paramètres. Vous pourriez avoir besoin de plus d'un objet paramètre.

def display_line(startPoint, endPoint, option1, option2)

pourrait devenir

def display_line(line, display_options)

/ 2 / L'objet paramètre peut avoir un nombre de propriétés inférieur au nombre initial de paramètres.

def double_click?(cursor_location1, control1, cursor_location2, control2)

pourrait devenir

def double_click?(first_click_info, second_click_info) 
                       # MouseClickInfo being the parameter object type 
                       # having cursor_location and control_at_click as properties

De telles utilisations vous aideront à découvrir les possibilités d'ajouter un comportement significatif à ces objets de paramètre. Vous constaterez qu'ils se débarrassent de leur odeur de classe de données initiale plus tôt pour votre confort. : -)





refactoring