Альтернативы для одиночного образца? - PullRequest
7 голосов
/ 03 июля 2010

Я уже некоторое время являюсь веб-разработчиком, использующим ASP.NET и C #, я хочу попробовать свои навыки, используя лучшие практики.

У меня есть веб-сайт.Я хочу загрузить настройки один раз и просто ссылаться на них там, где они мне нужны.Поэтому я провел небольшое исследование, и 50% разработчиков, похоже, используют для этого шаблон синглтона.А остальные 50% разработчиков - муравьиные синглтоны.Все они ненавидят одиночек.Они рекомендуют внедрение зависимостей.

Почему синглеты плохие?Как лучше загружать настройки веб-сайтов?Должны ли они быть загружены только один раз и ссылаться там, где это необходимо?Как бы я поступил так с внедрением зависимости (я новичок в этом)?Есть ли образцы, которые кто-то мог бы порекомендовать для моего сценария?И я также хотел бы видеть некоторый код модульного теста для этого (для моего сценария).

Спасибо, Брендан

Ответы [ 4 ]

6 голосов
/ 03 июля 2010

Как правило, я избегаю синглетонов, потому что они затрудняют юнит-тестирование вашего приложения.Синглтоны сложно смоделировать для юнит-тестов именно из-за их природы - вы всегда получаете один и тот же, а не тот, который вы легко можете настроить для юнит-теста.Данные конфигурации - строго типизированные данные конфигурации, в любом случае - это одно исключение, которое я делаю.Обычно данные конфигурации в любом случае относительно статичны, и альтернатива включает в себя написание достаточного количества кода, чтобы избежать статических классов, которые фреймворк предоставляет для доступа к web.config в любом случае.

Существует несколько различных способов его использования, которыевсе еще позволит вам тестировать приложение.Один из способов (может быть, в обоих случаях, если ваш синглтон не читает лениво app.cofnig), это иметь файл app.config по умолчанию в вашем проекте модульных тестов, предоставляющий значения по умолчанию, необходимые для ваших тестов.Вы можете использовать отражение, чтобы заменить любые конкретные значения, необходимые для ваших юнит-тестов.Как правило, я настраиваю приватный метод, который позволяет удалять частный экземпляр синглтона при настройке теста, если я внесу изменения для определенных тестов.

Другой способ состоит в том, чтобы фактически не использовать синглтон напрямую, а создатьинтерфейс для него, который реализует класс singleton.Вы можете использовать ручную инъекцию интерфейса, по умолчанию к экземпляру singleton, если предоставленное значение равно нулю.Это позволяет вам создать фиктивный экземпляр, который вы можете передать тестируемому классу для своих тестов, но в своем реальном коде используйте экземпляр singleton.По сути, каждый класс, который нуждается в этом, поддерживает частную ссылку на экземпляр singleton и использует его.Мне нравится этот способ немного лучше, но поскольку синглтон будет создан, вам все равно может понадобиться файл app.config по умолчанию, если только все значения не загружены лениво.

public class Foo
{
    private IAppConfiguration Configuration { get; set; }

    public Foo() : this(null) { }

    public Foo( IAppConfiguration config )
    {
        this.Configuration = config ?? AppConfiguration.Instance;
    }

    public void Bar()
    {
         var value = this.Config.SomeMaximum;
         ...
    }
}    
1 голос
/ 03 июля 2010

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

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

1 голос
/ 03 июля 2010

Здесь хорошее обсуждение шаблонов синглтона и примеров кодирования здесь ... http://en.wikipedia.org/wiki/Singleton_pattern См. Также здесь ... http://en.wikipedia.org/wiki/Dependency_injection

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

0 голосов
/ 27 апреля 2013

Один из способов решения этой проблемы - порвать ее как проблему DAL.

Какой бы класс / веб-страница и т. П. Не нуждался в использовании настроек конфигурации, следует объявить зависимость отIConfigSettingsService (фабрика / хранилище / все, что вам нравится, чтобы позвонить им).

private IConfigSettingsService _configSettingsService;

public WebPage(IConfigSettingsService configSettingsService)
{
    _configSettingsService = configSettingsService;
}

Таким образом, ваш класс получит такие настройки:будет иметь зависимость, которая является классом Dal.Как этот Dal заполнил бы объект ConfigSettings? Кому интересно.

  • Может быть, он будет каждый раз заполнять ConfigSettings из базы данных или XML-файла .config.

  • Возможно, он делает это в первый раз, но затем заполняет статические _configSettings для последующих вызовов.

  • Возможно, он получит настройки от Redis.Если что-то указывает на то, что настройки изменились, dal, или что-то внешнее, может обновить Redis.(Этот подход будет полезен, если у вас есть более одного приложения, использующего настройки.

Независимо от того, что он делает, ваша единственная зависимость - это не-одиночный интерфейс службы. Это очень легко смоделироватьВ ваших тестах вы можете заставить его возвращать ConfigSettings с тем, что вы хотите в нем).

В действительности это, скорее всего, будет MyPageBase, который имеет зависимость IConfigSettingsService, но он также может быть веб-службойслужба Windows, MVC somewhatsit или все вышеперечисленное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...