Domanda

Un'applicazione di database che sto attualmente lavorando, negozi di tutti i tipi di impostazioni nel database.La maggior parte delle impostazioni sono lì per personalizzare alcune regole di business, ma ci sono anche alcune altre cose in là.

L'app contiene oggetti che facciano una determinata attività, ad esempio, di una certa complessità del calcolo.Coloro che non UI sono oggetti di unità di test, ma anche la necessità di accedere a un sacco di quelle impostazioni globali.Il modo in cui abbiamo implementato questo proprio ora, è da dare la proprietà di oggetti che vengono riempiti con il Controller dell'Applicazione in fase di esecuzione.Quando il test di creare oggetti in prova e inserire i valori per i test (non dal database).

Questo funziona meglio, in ogni caso molto meglio che avere tutti quegli oggetti bisogno di un po globale Impostazioni oggetto --- che, naturalmente, in modo efficace test di unità impossibile :) Svantaggio può essere che a volte è necessario impostare una dozzina di proprietà, o che avete bisogno di lasciare quelle proprietà 'percolato' in sub-oggetti.

Quindi la domanda generale è:come si fa a fornire l'accesso globale delle impostazioni dell'applicazione nei vostri progetti, senza la necessità per le variabili globali, pur essendo in grado di unit test il tuo codice?Questo deve essere un problema che è stato risolto 100 di volte...

(Nota:Io non sono un programmatore esperto, come avrete notato;ma mi piace imparare!E, naturalmente, ho già fatto la ricerca su questo argomento, ma sto cercando alcune esperienze di prima mano)

È stato utile?

Soluzione

Si potrebbe utilizzare Martin Fowlers ServiceLocator modello.In php potrebbe apparire come questo:

class ServiceLocator {
  private static $soleInstance;
  private $globalSettings;

  public static function load($locator) {
    self::$soleInstance = $locator;
  }

  public static function globalSettings() {
    if (!isset(self::$soleInstance->globalSettings)) {
      self::$soleInstance->setGlobalSettings(new GlobalSettings());
    }
    return self::$soleInstance->globalSettings;
  }
}

Codice di produzione, poi, inizializza il servizio locator come questo:

ServiceLocator::load(new ServiceLocator());

Nel test-codice, inserire i mock-impostazioni come questo:

ServiceLocator s = new ServiceLocator();
s->setGlobalSettings(new MockGlobalSettings());
ServiceLocator::load(s);

Si tratta di un repository per singleton che possono essere scambiati per scopi di test.

Altri suggerimenti

Mi piace il modello di configurazione di fuori del Servizio Locator modello.Questo mi dà un solo punto per ottenere qualsiasi valore di configurazione che ho bisogno e mettendolo al di fuori dell'applicazione in una libreria separata, permette il riutilizzo e la testabilità.Ecco qualche esempio di codice, non sono sicuro di quale lingua si sta utilizzando, ma l'ho scritto in C#.

Prima ho creato una classe generica che i modelli di mio ConfigurationItem.

public class ConfigurationItem<T>
{
    private T item;

    public ConfigurationItem(T item)
    {
        this.item = item;
    }

    public T GetValue()
    {
        return item;
    }
}

Poi ho creato una classe che espone public static readonly variabili per l'elemento di configurazione.Qui sto solo leggendo il ConnectionStringSettings da un file di configurazione, che è appena xml.Naturalmente, per di più elementi, è possibile leggere i valori da qualsiasi fonte.

public class ConfigurationItems
{
    public static ConfigurationItem<ConnectionStringSettings> ConnectionSettings = new ConfigurationItem<ConnectionStringSettings>(RetrieveConnectionString());

    private static ConnectionStringSettings RetrieveConnectionString()
    {
        // In .Net, we store our connection string in the application/web config file.
        // We can access those values through the ConfigurationManager class.
        return ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["ConnectionKey"]];
    }
}

Poi, quando ho bisogno di un ConfigurationItem per l'uso, io la chiamo così:

ConfigurationItems.ConnectionSettings.GetValue();

E si tornerà a me un tipo sicuro valore, che poi posso cache o fare quello che voglio con.

Ecco un esempio di test:

[TestFixture]
public class ConfigurationItemsTest
{
    [Test]
    public void ShouldBeAbleToAccessConnectionStringSettings()
    {
        ConnectionStringSettings item = ConfigurationItems.ConnectionSettings.GetValue();
        Assert.IsNotNull(item);
    }
}

Spero che questo aiuta.

Questo è di solito gestito da un file ini o file di configurazione XML.Poi basta avere una classe che legge l'impostazione quando necessiti.

.NET ha costruito in questo con ConfigurationManager classi, ma è abbastanza facile da implementare, basta leggere i file di testo, o caricare il documento XML in DOM o analizzare a mano, in codice.

Avendo i file di configurazione del database è ok, ma non si legano al database e crea un extra relative alle dipendenze per le app che ini/file xml risolvere.

Ho fatto questo:

public class MySettings
{
    public static double Setting1
        { get { return SettingsCache.Instance.GetDouble("Setting1"); } }

    public static string Setting2
        { get { return SettingsCache.Instance.GetString("Setting2"); } }
}

Ho messo questo in un'infrastruttura separata modulo per rimuovere eventuali problemi di dipendenze circolari.
Facendo questo non mi sento legato ad uno specifico metodo di configurazione, e non hanno le stringhe in esecuzione il caos nel mio codice di applicazioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top