Classe / structure de configuration: modèle ou anti-modèle? Des alternatives?

10

Si vous ajoutez de nouvelles options de configuration à un programme, il peut souvent y avoir des tonnes d'effets d'entraînement en termes d'obtention des options là où elles doivent être appliquées. À ma connaissance, il existe trois façons de gérer ce problème:

  1. Passez tous les paramètres de configuration aux parties de votre programme qui en ont explicitement besoin en tant que primitives. C'est le moyen le plus explicite et le plus découplant. L'inconvénient est que c'est à la fois verbeux et cassant.

  2. Rendez les paramètres de configuration les plus fréquemment utilisés globaux / statiques. C'est le moyen le plus simple mais introduit une action à distance, entrave la testabilité et suppose que la configuration est vraiment globale (que vous ne voudriez qu'une seule configuration à un moment donné).

  3. Créez une classe / structure de configuration qui contient toutes les options de configuration pour l'ensemble du programme ou pour chaque problème majeur du programme, puis transmettez-le explicitement. Ceci est moins explicite que (1) mais plus explicite que (2). Si vous souhaitez modifier un paramètre uniquement pour un appel de fonction, vous pouvez cloner l'objet de configuration et modifier cette valeur. Ceci est utile à la fois dans les tests et dans la pratique. Cependant, vous finissez toujours par transmettre des tonnes d'informations à une fonction dont elle n'a pas besoin et la modification d'une valeur dans la classe / structure de configuration peut toujours provoquer une action à distance.

Considérez-vous (3) un motif ou un anti-motif? Si c'est un anti-pattern, que faites-vous à la place?

dsimcha
la source
Que diriez-vous d'une variation sur 3 - ayant plusieurs classes de configuration, en passant celle appropriée à l'endroit où cela est nécessaire?
Odé
@Oded: Je voulais souligner cela comme une possibilité. Édité.
dsimcha

Réponses:

4

La meilleure solution serait de faire plusieurs interfaces de configuration et de les implémenter à votre guise. Cela limite à la fois l'accessibilité et maintient les choses localisées. Cependant, c'est beaucoup trop d'efforts pour en valoir la peine plutôt que de simplement jeter toutes les config dans une seule classe et de passer à un problème avec beaucoup plus de gravité. C'est la configuration, pas l'UtterlyCrucialAlwaysChangingClass - elle restera à peu près la même. Tant que vous ne rendez pas tout cela global et que la mise en œuvre est cohérente, je ne m'en inquiéterais pas.

DeadMG
la source
4
+1 pour avoir déclaré que quelque chose n'est pas une conception théoriquement idéale, mais pourrait tout de même être bon dans la pratique lorsque l'on considère la simplicité et la probabilité de changement (ou son absence).
dsimcha
Je viens de jeter quatre arguments et de le remplacer par une classe Settings. C'était la bonne chose.
Martin Ueding
Je ne comprends pas laquelle des 3 options vous préconisez. Pourriez-vous préciser?
DBedrenko
1

Je préfère votre option 1 car le découplage permet des tests plus faciles et les paramètres de configuration dont dépend l'objet sont rendus explicites. Si un objet nécessite un paramètre de configuration, fournissez-le explicitement à l'objet par un argument constructeur ou une méthode setter. Réduisez la verbosité en utilisant un framework d'injection de dépendances pour injecter ces paramètres de configuration dans l'objet.

Jim Huang
la source
Vous vous êtes contredit: vous dites d'utiliser l'option 1, mais dites ensuite "Réduisez la verbosité en utilisant un cadre d'injection de dépendances pour injecter ces paramètres de configuration dans l'objet". qui est l'option 3: injection de constructeur.
DBedrenko
0

Imaginez si votre fichier de configuration a été écrit en XML. Vous pouvez ensuite simplement passer des fragments de ce XML à chacun de vos composants, afin qu'ils obtiennent leurs données de configuration.

Si vous utilisez .NET, vous pouvez créer des classes avec DataContracts que vous pouvez utiliser XmlSerialiser pour créer une hiérarchie d'objets à partir de votre configuration Xml et transmettre ces objets comme configuration.

Cela vous présente ensuite le problème suivant. Vos données de configuration comportent trois parties différentes. La configuration d'application structurelle qui organise vos bibliothèques de code pour se comporter comme ce produit spécifique. Paramètres de configuration du site qui contiennent les paramètres spécifiques à votre installation et les données de préférences / paramètres utilisateur qui varient avec chaque utilisateur de votre système.

Savoir quelle partie est laquelle et conserver ces paramètres de données séparés rendra l'installation des mises à jour beaucoup plus simple (sans perdre les paramètres des clients)

Michael Shaw
la source
0

Je rendrais la classe de l'option 3 statique. Donc au lieu de

//create SomeCl
Foo f = new Foo();
f.setConfigInst(cfg);
...
...
//Inside Foo
public void setConfig(MyAppConfig c) { localCfg = c; }
...
//somewhere else:
x = localCfg.getConfigForX();

Vous pouvez simplement avoir:

//Inside Foo
x = MyAppConfig.getConfigForX();

Laissez les détails du chargement / enregistrement des données de configuration se produire dans la MyAppConfigclasse. Et bien sûr, vous pourriez avoir des variations plus complexes, telles que différentes classes à des fins différentes.

Le seul cas où cette approche serait un problème serait si, pour une raison quelconque, vous deviez travailler sur plusieurs instances de configurations différentes en même temps , même si je n'ai pas encore rencontré une telle situation.

FrustratedWithFormsDesigner
la source
1
C'est ce qui se passe à peu près lors de l'exécution de tests unitaires dans certains cadres de test ... Mais même sans tests unitaires explicitement parallèles, cela va être pénible de tester des objets unitaires qui dépendent de l'état global.
Péter Török
0

Je travaille sur un projet où nous utilisons l'approche "3 couches (interface, logique métier, accès aux données)". L'application peut être un serveur Web multi-utilisateurs ou un serveur client.

Nous travaillons avec 3 configurations différentes, la première spécifique au PC, plus l'utilisateur travaille. Le deuxième spécifique pour l'utilisateur actuel et une troisième configuration globale pour tous les utilisateurs et applications client.

Chaque configuration est représentée dans chaque instance de l'application par un objet.

Cette approche peut aider votre projet.

umlcat
la source