Je vais supposer que vous voulez dire C# . Certains de ces éléments s'appliquent également à d'autres langues.
Vous avez plusieurs possibilités :
passer du constructeur aux régleurs de propriétés . Cela peut rendre le code plus lisible, car il est évident pour le lecteur de savoir quelle valeur correspond à quel paramètre. La syntaxe de l'initialisateur d'objet rend cela agréable. Elle est également simple à mettre en œuvre, car vous pouvez simplement utiliser des propriétés générées automatiquement et ne pas écrire les constructeurs.
class C
{
public string S { get; set; }
public int I { get; set; }
}
new C { S = "hi", I = 3 };
Cependant, vous perdez l'immuabilité et vous perdez la possibilité de vous assurer que les valeurs requises sont définies avant d'utiliser l'objet au moment de la compilation.
Modèle de construction .
Pensez à la relation entre string
y StringBuilder
. Vous pouvez l'obtenir pour vos propres classes. J'aime l'implémenter comme une classe imbriquée, donc la classe C
a une classe connexe C.Builder
. J'aime aussi une interface fluide sur le constructeur. Si elle est bien faite, vous pouvez obtenir une syntaxe comme celle-ci :
C c = new C.Builder()
.SetX(4) // SetX is the fluent equivalent to a property setter
.SetY("hello")
.ToC(); // ToC is the builder pattern analog to ToString()
// Modify without breaking immutability
c = c.ToBuilder().SetX(2).ToC();
// Still useful to have a traditional ctor:
c = new C(1, "...");
// And object initializer syntax is still available:
c = new C.Builder { X = 4, Y = "boing" }.ToC();
J'ai un script PowerShell qui me permet de générer le code constructeur pour faire tout cela, où l'entrée ressemble à :
class C {
field I X
field string Y
}
Ainsi, je peux générer au moment de la compilation. partial
me permettent d'étendre à la fois la classe principale et le constructeur sans modifier le code généré.
Refactoring "Introduce Parameter Object" (introduction d'un objet paramètre) . Voir le Catalogue de remaniement . L'idée est que vous prenez certains des paramètres que vous passez et les mettez dans un nouveau type, puis passez une instance de ce type à la place. Si vous faites cela sans réfléchir, vous vous retrouverez au point de départ :
new C(a, b, c, d);
devient
new C(new D(a, b, c, d));
Cependant, cette approche a le plus grand potentiel pour avoir un impact positif sur votre code. Donc, continuez en suivant ces étapes :
-
Cherchez sous-ensembles de paramètres qui ont un sens ensemble. Regrouper tous les paramètres d'une fonction sans réfléchir ne vous apporte pas grand-chose ; l'objectif est d'avoir des regroupements qui ont un sens. Vous saurez que vous avez bien fait lorsque le nom du nouveau type sera évident.
-
Recherchez d'autres endroits où ces valeurs sont utilisées ensemble, et utilisez le nouveau type là aussi. Il y a de fortes chances pour que, lorsque vous avez trouvé un bon nouveau type pour un ensemble de valeurs que vous utilisez déjà partout, ce nouveau type ait également un sens dans tous ces endroits.
-
Recherchez les fonctionnalités qui se trouvent dans le code existant, mais qui appartiennent au nouveau type.
Par exemple, vous voyez peut-être un code qui ressemble à ceci :
bool SpeedIsAcceptable(int minSpeed, int maxSpeed, int currentSpeed)
{
return currentSpeed >= minSpeed & currentSpeed < maxSpeed;
}
Vous pourriez prendre le minSpeed
y maxSpeed
et les mettre dans un nouveau type :
class SpeedRange
{
public int Min;
public int Max;
}
bool SpeedIsAcceptable(SpeedRange sr, int currentSpeed)
{
return currentSpeed >= sr.Min & currentSpeed < sr.Max;
}
C'est mieux, mais pour vraiment tirer parti du nouveau type, déplacez les comparaisons dans le nouveau type :
class SpeedRange
{
public int Min;
public int Max;
bool Contains(int speed)
{
return speed >= min & speed < Max;
}
}
bool SpeedIsAcceptable(SpeedRange sr, int currentSpeed)
{
return sr.Contains(currentSpeed);
}
Y maintenant nous arrivons à quelque chose : la mise en œuvre de SpeedIsAcceptable()
dit maintenant ce que vous voulez dire, et vous avez une classe utile et réutilisable. (La prochaine étape évidente est de faire SpeedRange
à Range<Speed>
.)
Comme vous pouvez le constater, Introduire un paramètre-objet était un bon début, mais sa véritable valeur est qu'il nous a permis de découvrir un type utile qui manquait à notre modèle.
0 votes
Vous avez dit "structure". Ce terme a différentes connotations dans différents langages de programmation. Que voulez-vous dire ?
2 votes
Si vous cherchez un langage particulier pour désambiguïser, allez-y avec C#. Mais en fait, il s'agit d'un simple sac de propriétés. Il a différents noms de propriétés avec différents types. Il peut être défini comme une classe, une table de hachage, une structure ou autre.
0 votes
Cet article a de bonnes idées sur le sujet. Il est spécifique à Javascript, mais les principes peuvent être réappliqués à d'autres langages.