Конфиг Класс / Структура: Шаблон или Анти-Шаблон? Альтернативы?

10

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

  1. Передайте все параметры конфигурации тем частям вашей программы, которые явно нуждаются в них в качестве примитивов. Это наиболее явный способ и способ, который разъединяет вещи наиболее. Недостатком является то, что это и многословно и хрупко.

  2. Сделайте наиболее часто используемые настройки конфигурации глобальными / статическими. Это самый простой способ, но вводит действие на расстоянии, затрудняет тестируемость и предполагает, что конфигурация действительно глобальна (что вам может потребоваться только одна конфигурация в любой момент времени).

  3. Создайте класс / структуру конфигурации, которые содержат все параметры конфигурации для всей программы или для каждой основной проблемы в программе, а затем явно передайте ее. Это менее явно, чем (1), но более явно, чем (2). Если вы хотите изменить настройку только для одного вызова функции, вы можете клонировать объект конфигурации и изменить это значение. Это полезно как при тестировании, так и на практике. Тем не менее, вы все равно можете передать тонны информации в функцию, которая ей не нужна, и изменение значения в классе / структуре config все равно может вызвать действие на расстоянии.

Считаете ли вы (3) шаблон или анти-шаблон? Если это анти-шаблон, что вы делаете вместо этого?

dsimcha
источник
Как насчет варианта 3 - иметь несколько классов конфигурации, передавая соответствующий туда, где это необходимо?
Одед
@Oded: я хотел подчеркнуть это как возможность. Ред.
дсимча

Ответы:

4

Лучшим решением было бы сделать несколько конфигурационных интерфейсов и реализовать их , как вы хотите. Это ограничивает доступ и сохраняет локализацию. Тем не менее, это слишком много усилий, чтобы стоить того, чтобы просто перебрать весь конфиг в одном классе и перейти к проблеме с гораздо большим вниманием. Это конфигурация, а не UtterlyCrucialAlwaysChangingClass - она ​​останется прежней. Пока вы не сделаете все это глобальным и реализация будет последовательной, я бы не стал беспокоиться об этом.

DeadMG
источник
4
+1 за высказывание, что что-то не является теоретически идеальным дизайном, но все же может быть хорошим на практике, если учитывать простоту и вероятность изменения (или его отсутствия).
дсимча
Я просто выбросил четыре аргумента и заменил его классом настроек. Мне казалось, что это правильно.
Мартин Юдинг
Я не понимаю, какой из 3 вариантов вы защищаете. Не могли бы вы уточнить?
Д.Бедренко,
1

Я предпочитаю ваш вариант 1, потому что разделение облегчает тестирование, и параметры конфигурации, от которых зависит объект, сделаны явными. Если объект требует настройки конфигурации, то явно предоставьте его объекту с помощью аргумента конструктора или метода установки. Уменьшите детализацию, используя инфраструктуру внедрения зависимостей для внедрения этих параметров конфигурации в объект.

Джим Хуан
источник
Вы опровергли себя: вы говорите, что используете Вариант 1, но затем говорите: «Уменьшите многословность, используя инфраструктуру внедрения зависимостей для внедрения этих параметров конфигурации в объект». Вариант 3: конструктор инъекций.
Д.Бедренко
0

Представьте, что ваш файл конфигурации был написан на XML. Затем вы можете просто передать фрагменты этого XML каждому из ваших компонентов, чтобы они получили свои данные конфигурации.

Если вы используете .NET, вы можете создавать классы с DataContracts, которые вы можете использовать XmlSerialiser для создания иерархии объектов из вашей XML-конфигурации и передавать эти объекты как конфигурацию.

Это тогда вводит вас в следующую проблему. Ваши данные конфигурации состоят из трех разных частей. Конструктивная конфигурация приложения, которая организует ваши библиотеки кода для работы в качестве этого конкретного продукта. Параметры конфигурации сайта, которые содержат ваши специфические параметры установки и данные о предпочтениях пользователя / настройках, которые зависят от пользователя в вашей системе.

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

Майкл Шоу
источник
0

Я бы сделал класс в варианте № 3 статическим. Так что вместо

//create SomeCl
Foo f = new Foo();
f.setConfigInst(cfg);
...
...
//Inside Foo
public void setConfig(MyAppConfig c) { localCfg = c; }
...
//somewhere else:
x = localCfg.getConfigForX();

Вы можете просто иметь:

//Inside Foo
x = MyAppConfig.getConfigForX();

Пусть детали загрузки / сохранения данных конфигурации происходят внутри MyAppConfigкласса. И, конечно, у вас могут быть более сложные варианты, такие как разные классы для разных целей.

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

FrustratedWithFormsDesigner
источник
1
Вот что в значительной степени происходит при выполнении модульных тестов в некоторых средах тестирования ... Но даже без явно параллельных модульных тестов, будет трудно в объектах модульного тестирования, которые зависят от глобального состояния.
Петер Тёрёк
0

Я работаю над проектом, в котором мы используем подход «3 уровня (интерфейс, бизнес-логика, доступ к данным)». Приложение может быть многопользовательским веб-сервером или клиентским сервером.

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

Каждая конфигурация представлена ​​в каждом объекте приложения объектом.

Такой подход может помочь вашему проекту.

umlcat
источник