Как правильно использовать паттерны проектирования?

Всем доброго времени суток! Читаю сейчас книгу банды четырёх и в параллель "Паттерны проектирования" Фрименов. И некоторые вещи мне реально взрывают мозг.

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

Т.е. понятно, что у нас есть некоторые модули, которые могут (и возможно даже будут) использоваться в других местах (других проектах и т.п.). И там (в модулях/сервисах) ты реально используешь все эти паттерны и всё круто.

Но вот когда дело доходит до использования этих модулей, начинается какая то каша. Вот есть контроллеры/вьюхи (ещё что то). Они привязаны к конкретному проекту и нигде больше не будут использоваться (разве что в качестве сниппетов).
Зачем им передавать кучу зависимостей? Зачем их делать слабосвязанными?
Не проще ли им тянуть все зависимости из глобального объекта приложения (который, по сути, будет синглтоном и SL (Service Locator) или DIC (Dependency Injection Container))?

Может, я что-то не так понимаю?
  • Вопрос задан
  • 8933 просмотра
Решения вопроса 1
Привет, автор. Вот мои мысли по этому поводу:
1. Понимание паттернов программирования приходит только с опытом. Чтение одной лишь книги, без практики, практически ничего вам не даст. Материал быстро забудется. Лично я прочитал примерно половину книги, после чего пришлось её на время отложить. Как я и говорил - без тренировки на примерах материал быстро забылся. Вновь вспоминаться он стал при чтении книги "Принципы, паттерны и методики гибкой разработки на языке c#". В книге достаточно много подробных примеров, и именно после их выполнения я стал осознавать суть некоторых паттернов.
Разумеется нельзя считать, что паттерн - это какое-либо строгое правило. Часть паттернов мы реализуем сами ещё до прочтения каких-либо книг. Паттерн - это возможное и удобное решение, которое можно применить для решения какой-либо задачи. Не надо пытаться заучить паттерны или вставлять их везде, где можно. Нужно просто писать как можно больше кода, тогда уже автоматически начинаешь видеть ситуации, где можно применить паттерн.
2. По-поводу слабой связанности. Во всех книгах, разумеется, пишут, что слабая связанность - это хорошо. Но на самом деле такая архитектура не всегда оправдана, и специалисты в области разработки ПО об этом периодически напоминают. На практике это означает то, что не нужно везде применять интерфейсы только потому, что можно это делать. Если вы уверены, что ваши классы вряд ли будут когда-либо заменены другими, то лично я считаю, что они могут быть смело использованы друг-другом без принципа инверсии зависимостей. Ну и вопрос к модульному тестированию. Разумеется сильная связанность мешает модульному тестированию, но если вы не планируете его проводить, то быть может и не стоит строить избыточные абстракции.
Лично я также считаю, что вышесказанной в меньшей степени справедливо для прикладных и вэб-приложений (где действительно важна модульность и тестировании), и в большей степени справедливо для игровых приложений. Лично я вообще с трудом представляю игру, в которой каждый игровой объект (танк, самолёт например) будет реализовывать интерфейс, чтобы теоретически когда-нибудь мы заменили танк на био-робота. Но это так, лирика.
3. По-поводу повторного использования. Один мой товарищ - senior developer, работавший в серьёзных организациях, говорит, что повторное использование кода - это миф. Лично я повторно использовал разве что какие-нибудь вспомогательные функции. Ну или в лучшем случае несколько классов и интерфейсов для поддержки модульности. На мой взгляд, говорить о том, что можно взять и перенести из проекта в проект всю архитектуру особо не приходится.
4. По-поводу контроллеров. Насколько я понимаю (опыт в разработке небольшой) основной смысл делать контроллеры зависимыми от интерфейсов только в том, чтобы тестировать эти контроллеры (хотя я не совсем понимаю зачем). Контроллер - это действительно такая вещь, которая с большой вероятностью будет использоваться только на конкретном сайте. Также этот контроллер будет завязан на какой-то интерфейс, предоставляющий бизнес-логику. Опять же вероятность, что один класс бизнес-логики будет заменён другим классом с такими же методами - стремится к нулю, особенно если учитывать то, что класс бизнес-логики зависит от интерфейса, который предоставляет методы получения данных. (если вы хотите изменить способ получения данных - вы изменяете, К примеру, класс репозитория, бизнес логика остаётся той же). В связи с этим я вижу пока только одну причину завязывать контроллеры на интерфейсы, а не конкретные классы бизнес-логики - это тестирование. Вы стабите интерфейс бизнес-логики и тестируете контроллер независимо от всех остальных модулей. Если не прав, поправьте, конечно.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы