Pregunta

Una aplicación de base de datos que actualmente estoy trabajando, tiendas de todo tipo de ajustes en la base de datos.La mayoría de los ajustes son para personalizar ciertas reglas de negocio, pero también hay algunas otras cosas.

La aplicación contiene objetos que específicamente hacer una determinada tarea, por ejemplo, de un determinado cálculo complicado.Los no-objetos de interfaz de usuario son la unidad probada, pero también necesitan tener acceso a un montón de la configuración global.La manera en que hemos implementado esta ahora, es a través de las propiedades de los objetos que son ocupados por el Controlador de Aplicación en tiempo de ejecución.Cuando se prueba, vamos a crear los objetos de la prueba y rellene los valores de las pruebas (no de la base de datos).

Esto funciona mejor, en cualquier caso, mucho mejor que tener todos los objetos de la necesidad de algunos de global Configuración objeto --- que por supuesto hace que la unidad de prueba imposible :) Desventaja puede ser que a veces es necesario para establecer una docena de propiedades, o que usted necesita para dejar que esas propiedades 'cuela' en la sub-objetos.

Así que la pregunta general es:¿cómo se puede proporcionar el acceso a las opciones de la aplicación en sus proyectos, sin la necesidad de que las variables globales, mientras que todavía siendo capaz de unidad de prueba de su código?Este debe ser un problema que ha sido resuelto de 100 veces...

(Nota:No estoy demasiado de un programador experimentado, como te habrás dado cuenta;pero me encanta aprender!Y, por supuesto, ya he hecho la investigación en este tema, pero realmente estoy buscando algunas experiencias de primera mano)

¿Fue útil?

Solución

Usted podría utilizar Martin Fowlers ServiceLocator patrón.En php se podría parecer a esto:

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;
  }
}

Su producción código inicializa el servicio de localizador de como esta:

ServiceLocator::load(new ServiceLocator());

En la prueba de código, usted inserte su maqueta configuración como esta:

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

Es un repositorio de los únicos que se pueden intercambiar para propósitos de prueba.

Otros consejos

Me gusta el modelo de mi configuración de acceso en el Servicio de Localizador de patrón.Esto me da un punto único para obtener cualquier valor de configuración que necesito y por la puesta fuera de la aplicación en una biblioteca independiente, permite la reutilización y la capacidad de prueba.Aquí está el código de ejemplo, no estoy seguro de lo que el lenguaje que se usa, pero lo escribí en C#.

Primero creo una clase genérica que los modelos de mi ConfigurationItem.

public class ConfigurationItem<T>
{
    private T item;

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

    public T GetValue()
    {
        return item;
    }
}

Entonces puedo crear una clase que expone public static readonly variables para el elemento de configuración.Aquí estoy leyendo el ConnectionStringSettings de un archivo de configuración, que es justo xml.Por supuesto, para más artículos, usted puede leer los valores de cualquier fuente.

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"]];
    }
}

Luego, cuando necesito un ConfigurationItem para su uso, yo lo llamo como este:

ConfigurationItems.ConnectionSettings.GetValue();

Y va a volver a mí a un tipo de valor seguro, que puedo caché o hacer lo que quiera con el.

Aquí una muestra de prueba:

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

Espero que esto ayude.

Generalmente esto es manejado por un archivo ini o archivo de configuración XML.A continuación, sólo tiene una clase en la que se lee la configuración cuando neeed.

.NET tiene esta integrado con el ConfigurationManager clases, pero es muy fácil de implementar, acabo de leer archivos de texto, o de la carga de XML en el DOM o análisis de ellos con la mano en el código.

Tener los archivos de configuración en la base de datos está bien, pero no los atan a la base de datos, y crea un extra de dependencia para su aplicación a la que se ini/archivos xml resolver.

Hice esto:

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

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

Poner esto en una infraestructura independiente módulo de eliminar problemas con las dependencias circulares.
Haciendo esto no estoy atado a ninguna configuración específica del método, y no tienen cadenas de ejecución estragos en mi código de aplicaciones.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top