c# java - Est-il correct d'avoir une classe avec juste des propriétés à des fins de refactoring?




method clean (11)

Martin Fowler appelle cet objet Introduire un paramètre dans son livre Refactoring . Avec cette citation, peu de gens l'appellent une mauvaise idée.

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.


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.

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.


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. : -)


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.


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.


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.


Bien que refactoriser un objet de paramètre ne soit pas en soi une mauvaise idée, il ne devrait pas être utilisé pour cacher le problème qu'une classe qui a besoin de 30 données provenant d'ailleurs pourrait toujours être quelque chose d'une odeur de code. Le refactoring d'objet de paramètre Introduire devrait probablement être considéré comme une étape dans un processus de refactoring plus large plutôt que vers la fin de cette procédure.

L'une des préoccupations qu'il n'aborde pas vraiment est celle de Feature Envy. Est-ce que le fait que la classe transmise à l'objet Parameter soit si intéressé par les données d'une autre classe n'indique pas que peut-être les méthodes qui fonctionnent sur ces données doivent être déplacées vers l'emplacement des données? Il est vraiment préférable d'identifier les clusters de méthodes et de données qui les regroupent et de les regrouper en classes, augmentant ainsi l'encapsulation et rendant votre code plus flexible.

Après plusieurs itérations du comportement de séparation et des données sur lesquelles il opère dans des unités séparées, 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 car cela rendra votre code plus souple.


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.


public Class ClassName{
    public int PropName{get;set;}
    public ClassName{
        PropName=0;  //Default Value
    }
}




c# oop refactoring