«Я точно не знаю, что делает этот класс, но я уверен, что это важно!»
У паттернов проектирования — типовых решений, есть антиподы — типовые ошибки в проектировании. О паттернах проектирования написано достаточно книг, о антипаттернах — единицы. Вашему вниманию представлен вольный перевод статьи с сайта SourceMaking, описывающий один из таких антипаттернов (всего на сайте в разделе Software Development Antipatterns их представлено 14).
Наименование: Poltergeists (полтергейсты)
Другие наименования: Gypsy (цыган), Proliferation of Classes (рост количества классов), Big DoIt Controller Class
Масштаб: приложение
Рефакторинг: Ghostbusting (охота за привидениями)
Причина появления: непонимание концепций ООП, лень продумать архитектуру классов
Примечание: автор перевода ни в коем случае не претендует на звание гуру проектирования и поэтому просит не воспринимать статью с оттенком нравоучения. Главной целью статьи является более глубое понимание в сути вопроса и, возможно, выяснение, насколько описываемая ситуация жизненна.
История вопроса
Рассматриваемый антипаттерн под именем «Цыгане» был впервые представлен Майклом Акройдом (Michael Akroyd) на конференции Object World West в 1996 году. Акройд нашел поведение этого антипаттерна схожим с кочевой жизнью цыган, которые внезапно появляются и затем также внезапно исчезают. Чтобы передать в названии антипаттерна больше информации о его сути мы выбрали другое наименование: «Полтергейсты». Эти «беспокойные призраки» ведут свою — обособленную ночную жизнь. Этот термин лучше представляет концепцию «заглянуть, чтобы что-то сделать» данного антипаттерна и в то же время сохраняет метафору «вот они здесь а вот их уже нет» изначального наименования.
Среди LISP-программистов (как и среди прочих), бывают разработчики, которые получают удовольствие от максимального использования «побочных эффектов» ряда функций языка программирования для выполнения ключевых задач в их системе неявным образом. Анализ и понимание таких систем практически невозможен и любая попытка повторного использования зачастую становится бессмысленной.
Ровно как применение «побочных эффектов» является некорректным использованием языковых средств, также и появление классов-полтергейстов является результатом неправильного использования концепций проектирования.
Описание
Полтергейсты — это классы с ограниченной ответственностью и ролью в системе. Их эффективный жизненный цикл непродолжителен. Полтергейсты нарушают стройность архитектуры программного обеспечения, создавая избыточные (лишние) абстракции, они чрезмерно запутанны, сложны для понимания и трудны в сопровождении.
Данный антипаттерн типичен в ситуациях, когда проектировщики знакомы с процессом моделирования но не имеют достаточного опыта в создании объектно-ориентированных архитектур. В их архитектуре возможно идентифицировать один или более классов-полтергейстов, которые появляются на время для инициации какого-либо действия в другом, более постоянном (с большим временем жизни) классе. Акройд называет эти классы «Цыганские вагоны». Обычно такие классы задумываются как классы-контроллеры, которые существуют только для вызова методов других классов, зачастую в предопределенной последовательности. Обычно они очевидны, так как их имена часто заканчиваются на "_manager", "_controller".
Виновником появления антипаттерна «полтергейст» обычно является архитектор-новичок, который не в полной мере понимает концепции объектно-ориентированного проектирования. Классы-полтергейсты являются плохими архитектурными решениями по трем ключевым причинам:
- они необязательны и поэтому бесполезно тратят ресурсы каждый раз, когда они «появляются»;
- они неэффективны, потому что используют избыточные пути навигации (navigation paths);
- они мешают правильному объектно-ориентированному проектированию, так как без необходимости загружают модель объектов.
Признаки появления и последствия антипаттерна
- Избыточные пути навигации.
- Временные ассоциации (прим.: здесь и далее под «ассоциацией» принимается отношение связи из UML).
- Классы без состояния (содержащие только методы и константы).
- Временные объекты и классы (с непродолжительным временем жизни).
- Классы с единственным методом, который предназначен только для создания или вызова других классов посредством временной ассоциации.
- Классы с именами методов в стиле «управления», такие как start_process_alpha.
Типичные причины
- Отсутствие объектно-ориентированной архитектуры (архитектор не понимает объектно-ориентированной парадигмы).
- Неправильный выбор пути решения задачи. Вразрез с популярным мнением, объектно-ориентированный подход не обязательно единственно-правильное решение для всех задач. Как гласит один плакат: «Не существует правильного способа сделать ошибку». Для рассматриваемой проблемы это значит, что если объектно-ориентированный подход не является правильным выбором, то не существует правильного пути для его реализации.
- Предположения об архитектуре приложения на этапе анализа требований (до объектно-ориентированного анализа) могут также вести к проблемам на подобии этого антипаттерна.
Рефакторинг
Проблема полтергейстов решается удалением их из иерархии классов. Выполняемые ими «функции» должны быть замещены. Обычно это довольно просто сделать путем внесения тривиальных корректировок в архитектуру.
Ключ в решении — перенос управляющих действий полтергейста-контроллера (которые инкапсулированы нем) в классы, методы которых вызывает полтергейст.
Пример
Для более ясного понимания паттерна, рассмотрим пример на рисунке.
Мы видим, что класс Peach Canner Controller является «полтергейстом» потому что:
- имеет избыточные пути навигации ко всем другим классам в рассматриваемой системе;
- все его ассоциации танзитивны;
- он не имеет состояния;
- является временным классом, который существует только для того, чтобы вызывать другие классы посредством временных ассоциаций.
В данном примере, если мы удалим класс-полтергейст, то оставшиеся классы потеряют возможность взаимодействовать, а также не останется никакого порядка выполнения процессов. Поэтому нам необходимо разместить возможность взаимодействия в оставшейся иерархии. Заметьте, что определенные операции добавлены в каждый процесс таким образом, что каждый класс в отдельности осуществляет взаимодействие и обрабатывает результаты.
Связанные решения
«80%-е решение», обсуждаемое в антипаттерне Blob выглядит очень похожим на антипаттерн «полтергейст». Представленный класс «координатор» еще управляет всей или большей функциональностью системы и, как правило, обладает многими свойствами полтергейста.
Применимость к другим масштабам и уровням системы
Антипаттерн возникает тогда, когда разработчики проектируют также, как они реализуют систему (обычно — «by the seat of their pants»), а также может возникнуть как результат упущений в построении архитектуры системы.
Как и в случае с большинством антипаттернов проектирования, оба уровня — архитектурный и управленческий играют ключевую роль в предупреждении и последующей борьбе с ними. Появление антипаттерна зачастую признается именно с архитектурной точки зрения, и посредством эффективного управления стоит учитывать эту точку зрения сразу.
Менеджеры должны заботиться о том, чтобы объектно-ориентированные архитектуры оценивались квалифицированными архитекторами на самом раннем этапе их создания и регулярно в последующем. Это позволит избежать ошибок новичков, подобных этому антипаттерну. Лучше оплатить цену хорошей архитектуры заранее.
Автор: snasoft