J'ai cette fonction API :
public ResultEnum DoSomeAction(string a, string b, DateTime c, OtherEnum d,
string e, string f, out Guid code)
Je n'aime pas ça. Parce que l'ordre des paramètres devient inutilement significatif. Il devient plus difficile d'ajouter de nouveaux champs. Il est plus difficile de voir ce qui est transmis. Il est plus difficile de refactoriser une méthode en parties plus petites parce que cela crée un autre surcoût de passer tous les paramètres dans les sous-fonctions. Le code est plus difficile à lire.
J'ai trouvé l'idée la plus évidente : avoir un objet encapsulant les données et le faire circuler au lieu de passer chaque paramètre un par un. Voici ce que j'ai trouvé :
public class DoSomeActionParameters
{
public string A;
public string B;
public DateTime C;
public OtherEnum D;
public string E;
public string F;
}
Cela a réduit ma déclaration d'API à :
public ResultEnum DoSomeAction(DoSomeActionParameters parameters, out Guid code)
Joli. Cela semble très innocent, mais nous avons en fait introduit un énorme changement : nous avons introduit la mutabilité. Car ce que nous faisions auparavant était en fait de passer un objet anonyme immuable : les paramètres de la fonction sur la pile. Maintenant nous avons créé une nouvelle classe qui est très mutable. Nous avons créé la possibilité de manipuler l'état de la classe appelant . Ça craint. Maintenant je veux que mon objet soit immuable, qu'est-ce que je fais ?
public class DoSomeActionParameters
{
public string A { get; private set; }
public string B { get; private set; }
public DateTime C { get; private set; }
public OtherEnum D { get; private set; }
public string E { get; private set; }
public string F { get; private set; }
public DoSomeActionParameters(string a, string b, DateTime c, OtherEnum d,
string e, string f)
{
this.A = a;
this.B = b;
// ... tears erased the text here
}
}
Comme vous pouvez le voir, j'ai en fait recréé mon problème initial : trop de paramètres. Il est évident que ce n'est pas la bonne solution. Que vais-je faire ? La dernière option pour obtenir une telle immuabilité est d'utiliser une structure "readonly" comme celle-ci :
public struct DoSomeActionParameters
{
public readonly string A;
public readonly string B;
public readonly DateTime C;
public readonly OtherEnum D;
public readonly string E;
public readonly string F;
}
Cela nous permet d'éviter les constructeurs avec trop de paramètres et d'atteindre l'immuabilité. En fait, cela résout tous les problèmes (ordre des paramètres, etc.). Pourtant :
- Tout le monde (y compris FXCop & Jon Skeet) est d'accord pour dire que l'exposition des champs publics est mauvaise .
- Eric Lippert et al. s'appuyer sur des champs en lecture seule pour l'immutabilité est un mensonge .
C'est alors que j'ai été troublé et que j'ai décidé d'écrire cette question : Quel est le moyen le plus simple en C# d'éviter le problème du "trop de paramètres" sans introduire la mutabilité ? Est-il possible d'utiliser une structure readonly à cette fin sans que l'API soit mal conçue ?
CLARIFICATIONS :
- Veuillez supposer qu'il n'y a pas de violation du principe de responsabilité unique. Dans mon cas original, la fonction écrit simplement les paramètres donnés dans un seul enregistrement de la base de données.
- Je ne cherche pas une solution spécifique à la fonction donnée. Je cherche une approche généralisée de ces problèmes. Je suis spécifiquement intéressé par la résolution du problème du "trop grand nombre de paramètres" sans introduire la mutabilité ou une conception terrible.
UPDATE
Les réponses fournies ici présentent différents avantages/inconvénients. C'est pourquoi j'aimerais convertir ce site en un wiki communautaire. Je pense que chaque réponse avec un exemple de code et les avantages et inconvénients ferait un bon guide pour des problèmes similaires à l'avenir. J'essaie maintenant de trouver comment le faire.