Config Class / Struct: Pattern o Anti-Pattern? Alternative?


10

Se aggiungi nuove opzioni di configurazione a un programma, spesso può avere tonnellate di effetti a catena in termini di ottenere le opzioni su dove devono essere attuate. Sono a conoscenza di tre modi di base di cui sono a conoscenza:

  1. Passa tutte le impostazioni di configurazione alle parti del tuo programma che ne hanno bisogno esplicitamente come primitive. Questo è il modo più esplicito e il modo che disaccoppia le cose di più. Il rovescio della medaglia è che questo è sia prolisso che fragile.

  2. Rende globali / statiche le impostazioni di configurazione utilizzate più di frequente. Questo è il modo più semplice ma introduce un'azione a distanza, ostacola la testabilità e presuppone che la configurazione sia veramente globale (che si vorrebbe solo una configurazione in un dato momento).

  3. Crea una classe / struttura di configurazione che contenga tutte le opzioni di configurazione per l'intero programma o per ciascuna delle principali preoccupazioni all'interno del programma, quindi passa questo in modo esplicito. Questo è meno esplicito di (1) ma più esplicito di (2). Se si desidera modificare un'impostazione solo per una chiamata di funzione, è possibile clonare l'oggetto config e modificare questo valore. Ciò è utile sia nei test che nella pratica. Tuttavia, si finisce con il passare potenzialmente tonnellate di informazioni a una funzione che non è necessaria e la modifica di un valore nella classe / struttura di configurazione può comunque causare azioni a distanza.

Considereresti (3) un modello o un anti-modello? Se è un anti-pattern, cosa fai invece?


Che ne dici di una variazione su 3: avere diverse classi di configurazione, passando quella appropriata dove è necessaria?
Oded,

@Oded: intendevo enfatizzarlo come una possibilità. Modificato.
dsimcha,

Risposte:


4

La soluzione migliore sarebbe quella di creare diverse interfacce di configurazione e implementarle come desideri. Ciò limita l'accessibilità e mantiene le cose localizzate. Tuttavia, è uno sforzo troppo grande per valerne la pena semplicemente buttando tutte le configurazioni in una singola classe e passando a un problema con molte più gravitas. Questa è la configurazione, non UtterlyCrucialAlwaysChangingClass - resterà praticamente la stessa. Fintanto che non renderai tutto globale e l'implementazione sarà coerente, non me ne preoccuperei.


4
+1 per dire che qualcosa non è un progetto teoricamente ideale, ma potrebbe comunque essere buono in pratica quando si considera la semplicità e la probabilità di cambiamento (o mancanza di ciò).
dsimcha,

Ho appena eliminato quattro argomenti e l'ho sostituito con una classe Settings. Sembrava la cosa giusta.
Martin Ueding,

Non capisco quale delle 3 opzioni stai sostenendo. Potresti specificare?
DBedrenko,

1

Preferisco l'opzione 1 perché il disaccoppiamento consente di eseguire test più semplici e le impostazioni di configurazione da cui dipende l'oggetto sono rese esplicite. Se un oggetto richiede un'impostazione di configurazione, fornirlo esplicitamente all'oggetto tramite un argomento del costruttore o un metodo setter. Ridurre la verbosità utilizzando un framework di iniezione di dipendenza per iniettare tali impostazioni di configurazione nell'oggetto.


Ti sei contraddetto: dici di usare l'Opzione 1, ma poi dici "Riduci la verbosità usando un framework di iniezione di dipendenza per iniettare quelle impostazioni di configurazione nell'oggetto". che è l'opzione 3: iniezione del costruttore.
DBedrenko,

0

Immagina se il tuo file di configurazione è stato scritto in XML. È quindi possibile passare frammenti di questo XML a ciascuno dei componenti, in modo che ottengano i loro dati di configurazione.

Se si utilizza .NET, è possibile creare classi con DataContracts che è possibile utilizzare XmlSerialiser per creare una gerarchia di oggetti dall'Xml di configurazione e passare questi oggetti come configurazione.

Questo quindi ti introduce al prossimo problema. I dati di configurazione sono suddivisi in tre parti diverse. La configurazione dell'applicazione strutturale che organizza le librerie di codici in modo che si comportino come questo prodotto specifico. Impostazioni di configurazione del sito che contengono le impostazioni specifiche dell'installazione e i dati delle preferenze / impostazioni dell'utente che variano a seconda dell'utente sul sistema.

Sapere quale parte è quale e mantenere separate queste impostazioni dei dati renderà l'installazione degli aggiornamenti molto più semplice (senza perdere le impostazioni dei clienti)


0

Vorrei rendere statica la classe nell'opzione n. 3. Quindi invece di

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

Puoi semplicemente avere:

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

Consenti ai dettagli di caricare / salvare i dati di configurazione all'interno della MyAppConfigclasse. E ovviamente potresti avere variazioni più complesse, come classi diverse per scopi diversi.

L'unico caso in cui questo approccio sarebbe un problema sarebbe se per qualche motivo fosse necessario lavorare su più istanze di diverse configurazioni contemporaneamente , anche se non ho ancora incontrato una situazione del genere.


1
Il che è ciò che accade praticamente quando si eseguono test unitari in alcuni framework di test ... Ma anche senza test unitari esplicitamente paralleli, sarà una seccatura per gli oggetti unit test che dipendono dallo stato globale.
Péter Török,

0

Sto lavorando a un progetto in cui stiamo usando l'approccio "3 livelli (interfaccia, logica aziendale, accesso ai dati)". L'applicazione può essere un server Web multiutente o un server client.

Lavoriamo con 3 diverse configurazioni, la prima specifica per PC, mentre l'utente sta lavorando. Il secondo specifico per l'utente corrente e una terza configurazione globale per tutti gli utenti e le app client.

Ogni configurazione è rappresentata in ogni istanza dell'applicazione da un oggetto.

Questo approccio può aiutare il tuo progetto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.