Шаблони слід використовувати лише там, де вони можуть бути найкращим рішенням або допомогти у створенні хорошого рішення (ви згодні?).
Я бачу шаблони дизайну строго як деталі реалізації. Якщо ви документуєте ваші загальнодоступні API та програму в цій документації, загалом це не має значення (або сильно вплине на вас), де ви маєте шаблони дизайну. Тобто, ви не переходите "у мене тут схема моста, і я впроваджу відвідувача поверх цього". Натомість, це "цей клас матиме різні реалізації в різних операційних системах, тому він буде реалізований за допомогою мостового шаблону". Потім, використовуючи його, ви байдуже ставитеся до того, що він реалізується як міст - адже ви дивитесь на загальнодоступний API, а не на модель моста.
скільки зусиль потрібно реально інвестувати у створення нещільно зв'язаних, гнучких конструкцій?
Вільне зчеплення можна досягти, дотримуючись простого набору правил. Якщо ви поважаєте їх, ваш код буде (більше) зв'язаний, як ви його пишете (тобто будь-які зусилля вже є частиною процесу розробки).
Серед правил (не вичерпний перелік):
- визначте свої інтерфейси, роздумуючи (або записуючи) клієнтський код (як клас буде використовуватися), а не те, що буде робити клас (тобто, налаштовуючи інтерфейс, а не впроваджуючи)
- "скажи, не питай"
- побудувати об’єкти з уже створених частин
- передайте в конструктор фактичні об'єкти, які ви будете використовувати (не фабрики для членів, параметри для фабрик параметрів або щось подібне).
- DRY (якщо у вас є два рядки, які відображаються в одному порядку в двох місцях, витягніть їх в окрему функцію тощо).
- Якщо створення об'єкта є більш складною операцією, реалізуйте створення посередницьких частин як заводський метод / клас (тобто не в тілі конструктора).
- ЯГНІ (створюйте речі так, як вам потрібно, не раніше).
Ці правила дотримуються по-різному, залежно від мови, методології розробки, яку дотримується ваша команда (наприклад, TDD), часових обмежень бюджету тощо.
Наприклад, у Java є хорошою практикою визначати свій інтерфейс як interfaceта записувати клієнтський код на цьому (тоді інстанціювати інтерфейс класом реалізації).
У C ++, з іншого боку, у вас немає інтерфейсів, тому ви могли записувати інтерфейс лише як абстрактний базовий клас; Оскільки в C ++ ви користуєтеся успадкуванням лише тоді, коли у вас є вимоги до нього (і як таке уникайте накладних витрат непотрібних віртуальних функцій), ви, ймовірно, не визначатимете інтерфейс окремо, лише заголовок класу).
Ті, хто виступає проти моделей дизайну, кажуть, що витрати на використання цих моделей часто перевищують переваги.
Я думаю, що вони роблять це неправильно. Якщо ви пишете слабко поєднаний (і сухий) код, інтеграція моделей дизайну в нього приводить з мінімальними додатковими зусиллями. В іншому випадку вам доведеться адаптувати свій код для реалізації схеми дизайну.
Якщо вам доведеться зробити багато змін, щоб реалізувати схему дизайну, ваша проблема полягає не в шаблоні дизайну - це ваша база коду монолітна і щільно пов'язана. Це погана / неоптимальна проблема дизайну, а не проблема дизайнерських моделей.
Що я хотів би знати, - скільки зусиль я повинен докласти, щоб створити додаткові рівні абстрагування та дизайну, лише щоб дозволити моїй програмі слідувати принципам OO, таким як вільне з'єднання, програмування на інтерфейс тощо. Чи справді це варто? це? Скільки зусиль я повинен докласти до цього?
Ваші запитання роблять (нестандартним) припущення, що єдиною перевагою нещільного з’єднання є можливість легко впроваджувати дизайнерські шаблони. Це не так.
Серед переваг сипучої муфти:
- гнучкість рефакторингу та перепроектування
- менше марних зусиль
- заповітність
- збільшена можливість повторного використання коду
- простота дизайну
- менше часу, проведеного в налагоджувачі
... і кілька інших, які зараз не приходять мені в голову.