Come / quando "creare" un Singleton che memorizza i dati di configurazione

1

Sono uno sviluppatore junior (penso all'esperienza di livello interno) che lavora in un piccolo negozio più o meno da solo su un progetto che consuma dati da un database, lo elabora e inserisce i risultati in un altro database. La soluzione è un servizio di Windows scritto in C #.

Una versione precedente della soluzione utilizzava App.config per cose come stringhe di connessione, intervalli di tempo per controllare il db per i nuovi dati, ecc. Il project manager desidera che queste informazioni siano memorizzate in una tabella nel db, e quindi avere un singleton che mantenga quei dati piuttosto che aver bisogno di accedere al file di configurazione. I dati di configurazione devono essere caricati all'avvio.

La mia attuale implementazione ha il costruttore del singleton che effettua una singola chiamata a getConfig() , un metodo che incapsula il lavoro di ottenere tutti i dati dal db. Siamo ora in procinto di scrivere il codice che controllerà il db all'avvio per assicurarsi che quelle tabelle di configurazione siano presenti e le costruirà se non lo sono.

Ho diverse incertezze sul design:

1) Costruire la configurazione nel costruttore è il posto migliore in modo che il lavoro sia implicito:

protected override void OnStart(string[] args)
{
    // The first call for an instance, so the object is created & data is loaded
    ConfigSingleton MyConfig = ConfigSingleton.GetInstance;

    // Create object that checks db for data to process; relies on config
    Poller = new Poller(); 
    Poller.Start();
}

o dovrei effettuare una chiamata pubblica esplicita a getConfig() durante l'avvio per maggiore chiarezza:

protected override void OnStart(string[] args)
{
    ConfigSingleton MyConfig = ConfigSingleton.GetInstance;
    MyConfig.getConfig(); // Explicit call to get config from db

    // Create object that checks db for data to process; relies on config
    Poller = new Poller(); 
    Poller.Start();
}

2) Il lavoro per controllare le tabelle di configurazione dovrebbe essere fatto da una classe separata, presumibilmente statica:

protected override void OnStart(string[] args)
{
    if (!DBChecker.isTableReady())
    {
        DBChecker.BuildTables();
    }

    ConfigSingleton MyConfig = ConfigSingleton.GetInstance;
    MyConfig.getConfig();

    // Create object that checks db for data to process; relies on config
    Poller = new Poller(); 
    Poller.Start();
}

o dovrebbe essere gestito internamente dal singleton di configurazione, quindi il codice apparirebbe come una delle varianti sopra?

Un esempio un po 'non correlato che aiuta a chiarire lo spirito della mia domanda proviene da una versione precedente della soluzione (che ho parafrasato):

// Inside this function, a call is made to BusinessLayer.GetList1()
MyController = new Controller(FirstParam); 
MyController.Start();

// Yet here, a similar version is called first and then the result is passed as a parameter
List<Objects> MyList2 = BusinessLayer.GetList2();
MySender = new Sender(SecondParam, MyList2);
MySender.Start();

Ci sono delle regole di base che governano quando il lavoro dovrebbe essere svolto all'interno di un altro lavoro, o al di fuori, passato come parametro, ecc, a parte il fatto ovvio che dovrebbe essere almeno coerente?

    
posta Joseph 22.04.2015 - 18:12
fonte

2 risposte

0

1) Per motivi di chiarezza, ho deciso di andare con la chiamata pubblica a getConfig() .

2) La responsabilità dell'oggetto config è ottenere e memorizzare i dati dal db. Pertanto, sarebbe meglio avere una classe separata per eseguire il bootstrap delle tabelle di configurazione. Il mio codice ora assomiglia a qualcosa:

protected override void OnStart(string[] args)
{
    ConfigBootstrapper.GetConfigTablesReady();
    ConfigSingleton.GetInstance.getConfig();

    Poller = new Poller();
    Poller.Start();

    Logger.Warn("service started.");
}
    
risposta data 26.04.2015 - 15:05
fonte
5

In realtà ho appena risolto questo problema. Volevo memorizzare i dati di configurazione nel database mentre il programma consumava i dati. Ho creato una classe di richiamo della configurazione (non singleton) che, quando una parte del programma richiedeva un valore di configurazione, creava un'istanza della classe e chiamava il metodo GetConfigValue(ConfigPropertyEnum item) . Dietro la classe c'era una cache a cui si accedeva solo dalla classe di recupero della configurazione e una classe di repository per l'interfacciamento con il database (utilizzando Entity Framework).

Quando ho implementato la classe di recupero della configurazione per la prima volta, l'accesso al database tramite il repository è stato eseguito ogni volta che è stato necessario un valore di configurazione in modo che potessi iniziare a scrivere il resto del programma. Dopo aver convalidato che il progetto generale avrebbe funzionato, ho implementato la cache con un modo di timeout dei valori della cache in modo che periodicamente ricaricassi un elemento dal database nel caso in cui le cose cambiassero.

Questa struttura mi ha dato una configurazione liberamente accoppiata. Poiché al resto del programma non interessa come la classe di recupero della configurazione abbia ottenuto il valore, posso scambiare l'archivio dati effettivo dal file di configurazione al database e tornare indietro senza alcuna modifica al codice, tranne nella classe di recupero della configurazione. Inoltre, poiché ho un'interfaccia, posso sostituire la mia implementazione di cache senza dover cambiare il resto del programma finché l'interfaccia rimane la stessa.

Nel complesso ha fornito una classe di configurazione robusta ed estensibile. Quando voglio aggiungere una nuova variabile di configurazione posso aggiungere enum e tabella e avere il valore disponibile in qualsiasi punto del programma.

Come ottenere i valori di configurazione in altre parti del programma? Tendo ad apprezzare l'iniezione di dipendenza con le mie classi prendendo un'istanza di IConfiguration in modo da poter utilizzare diverse implementazioni se sto testando.

    
risposta data 22.04.2015 - 19:16
fonte

Leggi altre domande sui tag