2008-08-15 1 views
2

Приложение базы данных, в котором я сейчас работаю, сохраняет всевозможные настройки в базе данных. Большинство этих настроек настраивают определенные бизнес-правила, но есть и другие вещи.Доступ к глобальным настройкам приложения

Приложение содержит объекты, которые специально выполняют определенную задачу, например, определенный сложный расчет. Те объекты, которые не являются объектами UI, тестируются на единицу, но также нуждаются в доступе к множеству этих глобальных настроек. Способ, которым мы реализовали это прямо сейчас, заключается в предоставлении свойств объектов, которые заполняются Контроллером приложений во время выполнения. При тестировании мы создаем объекты в тесте и заполняем значения для тестирования (а не из базы данных).

Это работает лучше, в любом случае намного лучше, чем для того, чтобы все эти объекты нуждались в некотором глобальном объекте . объект --- это, конечно, эффективно делает модульное тестирование невозможным :) Недостатком может быть то, что вам иногда нужно установить дюжину свойства, или что вам нужно, чтобы эти свойства «перколировали» в под-объекты.

Таким образом, общий вопрос:: как вы предоставляете доступ к глобальным параметрам приложения в своих проектах, не требуя глобальных переменных, сохраняя возможность модульного тестирования кода? Это должна быть проблема, которая была решена в 100 раз ...

(Примечание: я не слишком опытный программист, как вы заметили, но я люблю учиться! И, конечно же, я «Я уже делал исследования в этой теме, но я действительно искал некоторые из первых рук)

ответ

1

Вы можете использовать шаблон Martin Fowlers ServiceLocator. В PHP это может выглядеть следующим образом:

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

Ваш код продукции затем инициализирует сервис локатора так:

ServiceLocator::load(new ServiceLocator()); 

В тестовом коде, вставив имитировали-настройки, как это:

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

Это репозиторий для синглетов, который можно обменять для целей тестирования.

0

Обычно это обрабатывается ini-файлом или файлом конфигурации XML. Тогда у вас есть класс, который читает настройку, когда будет отображаться.

.NET имеет встроенные классы ConfigurationManager, но его легко реализовать, просто прочитать текстовые файлы или загрузить XML в DOM или проанализировать их вручную в коде.

Наличие конфигурационных файлов в базе данных в порядке, но оно привязывает вас к базе данных и создает дополнительную зависимость для вашего приложения, которое разрешает файлы ini/xml.

0

Я сделал это:

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

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

Я положил это в отдельном модуле инфраструктуры для удаления каких-либо проблем с циклическими зависимостями.
Выполнение этого Я не привязан к какому-либо определенному способу конфигурации и не имеет никаких строк, которые могут привести к хаосу в моем коде приложений.

1

Мне нравится моделировать доступ к моей конфигурации из шаблона Locator службы.Это дает мне одно очко, чтобы получить любое значение конфигурации, которое мне нужно, и помещая его вне приложения в отдельную библиотеку, что позволяет повторно использовать и тестировать. Вот пример кода, я не уверен, какой язык вы используете, но я написал его на C#.

Сначала я создаю общий класс, который будет моделировать мой ConfigurationItem.

public class ConfigurationItem<T> 
{ 
    private T item; 

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

    public T GetValue() 
    { 
     return item; 
    } 
} 

Затем я создаю класс, который предоставляет публичные статические переменные readonly для элемента конфигурации. Здесь я просто читаю ConnectionStringSettings из файла конфигурации, который является просто xml. Конечно, для большего количества предметов вы можете прочитать значения из любого источника.

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

Затем, когда мне нужно ConfigurationItem для использования, я называю это так:

ConfigurationItems.ConnectionSettings.GetValue(); 

И это вернет мне безопасное значение типа, который я могу затем кэшировать или делать все, что я хочу с ,

Вот тестовый образец:

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

Надеется, что это помогает.

 Смежные вопросы

  • Нет связанных вопросов^_^