Я цілком прагматик, але моя головна турбота тут полягає в тому, що ви можете дозволити цьому ConfigBlock
домінувати над вашими конструкціями інтерфейсів, можливо, погано. Коли у вас є щось подібне:
explicit MyGreatClass(const ConfigBlock& config);
... Більш відповідний інтерфейс може бути таким:
MyGreatClass(int foo, float bar, const string& baz);
... на відміну від того, щоб просто збирати вишні з цих foo/bar/baz
масивів ConfigBlock
.
Лінивий дизайн інтерфейсу
З іншого боку, такий дизайн спрощує створення стабільного інтерфейсу для вашого конструктора, наприклад, оскільки якщо вам потрібне щось нове, ви можете просто завантажити його в ConfigBlock
(можливо, без змін коду), а потім вибирайте будь-які нові речі, які вам потрібні, без будь-яких змін інтерфейсу, лише зміни в реалізації MyGreatClass
.
Так що це одночасно і професіонал, і це, що це звільняє вас від створення більш ретельно продуманого інтерфейсу, який приймає лише ті дані, які йому фактично потрібні. Він застосовує мислення: "Просто дайте мені цей масивний обсяг даних, я виберу, що мені потрібно від нього" , на відміну від чогось більш схожого, "Ці точні параметри - це те, що цей інтерфейс повинен працювати".
Тож тут безумовно є деякі плюси, але вони можуть сильно перевершити мінуси.
Зчеплення
У цьому сценарії всі такі класи, що будуються з ConfigBlock
екземпляра, мають залежність таким чином:
Це може стати PITA, наприклад, якщо ви хочете Class2
ізолювати тест на цій діаграмі ізольовано. Можливо, вам доведеться поверхово моделювати різні ConfigBlock
вхідні дані, що містять відповідні поля Class2
, які зацікавлені, щоб мати змогу протестувати його в різних умовах.
У будь-якому новому контексті (будь то тестовий блок або весь новий проект), будь-які подібні класи можуть стати тягарем для (повторного) використання, оскільки ми змушені завжди брати ConfigBlock
з собою їзди та налаштовувати його. відповідно.
Можливість повторної використання / розгортання / завіреність
Натомість, якщо ви правильно розробите ці інтерфейси, ми можемо роз’єднати їх ConfigBlock
і закінчити щось подібне:
Якщо ви помітили на цій вище діаграмі, всі класи стають незалежними (їх аферентні / вихідні сполучення зменшуються на 1).
Це призводить до набагато більше незалежних класів (принаймні незалежних від ConfigBlock
), які можуть бути набагато простішими для (повторного) використання / тестування в нових сценаріях / проектах.
Тепер цей Client
код стає таким, який повинен залежати від усього і зібрати його разом. Навантаження в кінцевому підсумку переноситься на цей клієнтський код для зчитування відповідних полів з а ConfigBlock
та передачі їх у відповідні класи як параметри. Тим не менш, такий код клієнта, як правило, вузько розроблений для конкретного контексту, і його потенціал для повторного використання, як правило, має бути пшиком або закриттям у будь-якому разі (це може бути main
функцією точки входу програми або щось подібне).
Тож з точки зору повторного використання та тестування це може допомогти зробити ці класи більш незалежними. З точки зору інтерфейсу для тих, хто використовує ваші класи, це також може допомогти чітко вказати, які параметри їм потрібні, а не лише один масивний, ConfigBlock
який моделює весь всесвіт полів даних, необхідних для всього.
Висновок
Взагалі, такий клас, орієнтований на клас дизайну, який залежить від моноліту, який має все необхідне, має властивості такого роду. Їх застосовність, розгортаність, повторне використання, тестабельність тощо можуть в результаті значно погіршитись. Однак вони можуть настільки спростити дизайн інтерфейсу, якщо ми спробуємо на ньому позитивно повернутись. Ви вирішуєте оцінювати ці плюси і мінуси і вирішувати, чи варті цього компроміси. Зазвичай набагато безпечніше помилятися проти подібного дизайну, коли ви вибираєте вишню з моноліту в класах, які, як правило, призначені для моделювання більш загального та широко застосовуваного дизайну.
Останнє, але не менш важливе:
extern CodingBlock MyCodingBlock;
... це потенційно ще гірше (більш асиметричним?) З точки зору характеристик , описаних вище , ніж ін'єкції підходу залежно, як вона закінчується з'єднанням класи не тільки ConfigBlocks
, але і безпосередньо до конкретного екземпляру цього. Це ще більше погіршує застосовність / розгорнутість / доказовість.
Моя загальна порада буде помилятися на стороні проектування інтерфейсів, які не залежать від таких видів монолітів, щоб вказати їх параметри, принаймні для найбільш загальноприйнятих класів, які ви розробляєте. І уникайте глобального підходу без введення залежності, якщо можете, якщо у вас справді немає дуже сильних і впевнених причин не уникати цього.