Налаштувати клас / структуру: шаблон або анти-шаблон? Альтернативи?


10

Якщо додати в програму нові параметри конфігурації, вона часто може мати безліч ефектів пульсації з точки зору отримання варіантів того місця, де потрібно діяти. Є три основні способи впоратися з цим, про які я знаю:

  1. Передайте всі налаштування конфігурації частинам вашої програми, які явно потребують їх як примітиви. Це найбільш очевидний спосіб і спосіб, який розв'язує речі найбільше. Мінус у тому, що це одночасно багатослівний та крихкий.

  2. Зробіть параметри конфігурації, що найчастіше використовуються, глобальними / статичними. Це найпростіший спосіб, але вводить дії на відстані, перешкоджає встановленню і передбачає, що конфігурація справді є глобальною (що вам потрібно лише одна конфігурація в будь-який момент часу).

  3. Створіть клас / структуру конфігурації, що містить усі параметри конфігурації для всієї програми або для кожної основної проблеми в програмі, а потім явно передайте це навколо. Це менш явно, ніж (1), але більш явно, ніж (2). Якщо ви хочете змінити налаштування лише для одного виклику функції, ви можете клонувати об’єкт конфігурації та змінити це одне значення. Це корисно як на тестуванні, так і на практиці. Однак ви все-таки потенційно передаєте тонни інформації функції, яка їй не потрібна, і зміна значення в класі / структурі config все одно може викликати дію на відстані.

Чи вважаєте ви (3) шаблоном чи антидіаграмою? Якщо це анти-візерунок, що ви робите замість цього?


Як щодо варіації на 3 - з кількома класами конфігурації, передаючи відповідний туди, куди це потрібно?
Одід

@Oded: Я мав намір підкреслити це як можливість. Відредаговано.
dimimcha

Відповіді:


4

Кращим рішенням було б зробити кілька конфігураційних інтерфейсів і реалізувати їх , як ви хочете. Це і обмежує доступність, і зберігає речі локалізованими. Однак, це занадто багато зусиль, щоб того вартувати над тим, щоб просто зафіксувати конфігурацію в одному класі та перейти до проблеми з набагато більшою кількістю гравітацій. Це конфігурація, а не UtterlyCrucialAlwaysChangingClass - це майже все, що залишиться колишнім. Поки ви не зробите це все глобальним, а впровадження послідовно, я б не переживав про це.


4
+1 за те, що щось теоретично не є ідеальним дизайном, але все-таки може бути корисним на практиці, коли розглядається простота та ймовірність змін (або їх відсутності).
дзимча

Я просто викинув чотири аргументи і замінив його класом Налаштування. Це здавалося правильним.
Мартін Удінг

Я не розумію, який із трьох варіантів ви виступаєте. Не могли б ви вказати?
DBedrenko

1

Я віддаю перевагу вашому варіанту 1, оскільки розв'язка дозволяє простіше тестувати, а параметри конфігурації, від яких залежить об'єкт, стають явними. Якщо об'єкт вимагає налаштування конфігурації, тоді явно надайте його об'єкту аргументом конструктора або методом setter. Зменшіть багатослів’я, використовуючи рамку введення залежності, щоб ввести ці параметри конфігурації в об’єкт.


Ви суперечили собі: ви скажете скористатися Варіантом 1, а потім сказати "Зменшіть багатослів’я, використовуючи рамку введення залежності, щоб ввести ці параметри конфігурації в об'єкт". що є Варіант 3: впорскування конструктора.
DBedrenko

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класу. І звичайно, у вас можуть бути складніші варіанти, наприклад, різні класи для різних цілей.

Єдиним випадком, коли такий підхід був би проблемою, був би, якщо вам з якихось причин потрібно було працювати над декількома екземплярами різних конфігурацій одночасно , хоча я ще не стикався з такою ситуацією.


1
Що багато чого відбувається при запуску одиничних тестів у деяких тестових рамках ... Але навіть без явно паралельних одиничних тестів, це буде біль у попці для одиниць тестових об'єктів, які залежать від глобального стану.
Péter Török

0

Я працюю над проектом, де ми використовуємо підхід "3 рівня (інтерфейс, бізнес-логіка, доступ до даних)". Додаток може бути багатокористувацьким веб-сервером або клієнтським сервером.

Ми працюємо з 3 різними конфігураціями, першою специфікою для ПК, на якій працює користувач. Друга специфічна для поточного користувача та третя глобальна конфігурація для всіх користувачів та клієнтських додатків.

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

Цей підхід може допомогти вашому проекту.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.