Антипаттерны (anti-patterns)

Антипаттерны в противовес практики хорошего программирования — это классы наиболее часто внедряемых плохих решений проблем. Они изучаются как категория, чтобы избежать проблем в будущем либо распознать отдельные случаи их применения при изучении неработающих систем.

Впервые термин «Антипаттерн» в смысле формальной модели типичного неудачного решения используется в 1996 г. Майклом Эйкройдом (англ. Michael Akroyd) на конференции «Object World West Conference», посвященной аспектам объектно-ориентированного программирования [631. В своей презентации «Антипаттерны: предотвращение неправильного использования объектов» Эйкройд обращал внимание на вредные, но частые программные конструкции, в частности те, что противоречат принципам ООП. К тому же для каждой такой конструкции он предлагал эффективную замену.

Частью хорошей практики программирования считается программирование без антипаттернов. У программистов, как и у работников любой сферы деятельности, можно выделить типичные ошибки, обусловленные недостаточной базой знаний или отсутствием опыта, сжатыми сроками сдачи проекта, финансовыми ограничениями и пр. [64J.

Некоторые различаемые антипаттерны

в программировании

Антипаттерны в управлении разработкой ПО:

  • • Дым и зеркала (Smoke and mirrors): демонстрация того, как будут выглядеть ненаписанные функции (название происходит от двух излюбленных способов, которыми фокусники скрывают свои секреты).
  • Раздувание ПО (Software bloat): разрешение последующим версиям системы требовать все больше и больше ресурсов.
  • • Функции для галочки: превращение программы в конгломерат плохо реализованных и не связанных между собой функций (как правило, для того, чтобы заявить в рекламе, что функция есть).

Антипаттерны в проектировании ПО:

  • • Инверсия абстракции (Abstraction inversion): сокрытие части функциональности от внешнего использования в надежде на то, что никто не будет его использовать.
  • • Неопределенная точка зрения (Ambiguous viewpoint): представление модели без спецификации ее точки рассмотрения.
  • • Большой комок грязи (Big ball of mud): система с нераспознаваемой структурой.
  • • Бензиновая фабрика (Gas factory): необязательная сложность дизайна.
  • • Затычка на ввод данных (Input kludge): забывчивость в спецификации и выполнении поддержки возможного неверного ввода.
  • • Раздувание интерфейса (Interface bloat): разработка интерфейса очень мощным и очень сложным для реализации.
  • • Волшебная кнопка (Magic pushbutton): выполнение результатов действий пользователя в виде неподходящего (недостаточно абстрактного) интерфейса. Например, в системах типа Delphi это написание прикладной логики в обработчиках нажатии на кнопку.
  • • Перестыковка (Re-Coupling): процесс внедрения ненужной зависимости.
  • • Дымоход (Stovepipe system): редко поддерживаемая сборка плохо связанных компонентов.
  • • Состояние гонки (Race hazard, Race condition): непредвидение возможности наступления событий в порядке, отличном от ожидаемого.
  • • Мышиная возня: неоправданное создание множества мелких и абстрактных классов для решения одной конкретной задачи более высокого уровня.
  • • Висящие концы: интерфейс, большинство методов которого бессмысленны и реализуются «пустышками».
  • • Золушкина туфелька: попытка «натянуть» на объект уже имеющийся малоподходящий по смыслу интерфейс вместо создания нового.
  • • Членовредительство (Mutilation): излишнее «затачивание» объекта под определенную очень узкую задачу таким образом, что он не способен будет работать с никакими иными, пусть и очень схожими задачами.

Антипаттерны в объектно-ориентированном

программировании:

  • • Базовый класс-утилита (BaseBean): наследование функциональности из класса-утилиты вместо делегирования к нему.
  • • Вызов предка (CallSuper): для реализации прикладной функциональности методу класса-потомка требуется в обязательном порядке вызывать те же методы класса-предка.
  • • Ошибка пустого подкласса (Empty subclass failure): создание класса (в Perl), который не проходит «проверку пустоты подкласса» («Empty Subclass Test») из-за различного поведения по сравнению с классом, который наследуется от него без изменений.
  • • Божественный объект (God object): концентрация слишком большого количества функций в одной части системы (классе).
  • • Объектная клоака (Object cesspool): переиспользование объектов, находящихся в непригодном для переиспользования состоянии.
  • • Полтергейст (Poltergeist): объекты, чье единственное предназначение — передавать информацию другим объектам.
  • • Проблема йо-йо (Yo-yo problem): чрезмерная размытость сильно связанного кода (например, выполняемого по порядку) по иерархии классов.
  • • Одиночество (Singletonitis): неуместное использование паттерна Одиночка.
  • • Приватизация (Privatisation): сокрытие функциональности в приватной секции (private), что затрудняет его расширение в классах-потомках.
  • • Френд-зона (Friend zone): неуместное использование дружественных классов и дружественных функций в языке C++.
  • • Каша из интерфейсов (Interface soup): объединение нескольких интерфейсов, разделенных согласно принципу изоляции интерфейсов (Interface Segregation), в один.

Антипаттерны в программировании:

  • • Ненужная сложность (Accidental complexity): внесение ненужной сложности в решение.
  • • Действие на расстоянии (Action at а distance): неожиданное взаимодействие между широко разделенными частями системы.
  • • Накопить и запустить (Accumulate andssre): установка параметров подпрограмм в наборе глобальных переменных.
  • • Слепая вера (Blindfaith): недостаточная проверка корректности исправления ошибки или результата работы подпрограммы.
  • • Лодочный якорь (Boat anchor): сохранение более не используемой части системы.
  • • Активное ожидание (Busy spin): потребление ресурсов ЦПУ (процессорного времени) во время ожидания события, обычно при помощи постоянно повторяемой проверки, вместо того чтобы использовать асинхронное программирование (к примеру, систему сообщений или событий).
  • • Кэширование ошибки (Cachingfailure): забывать сбросить флаг ошибки после ее обработки.
  • • Воняющий подгузник (The Diaper Pattern Stinks): сброс флага ошибки без ее обработки или передачи вышестоящему обработчику.
  • • Проверка типа вместо интерфейса (Checking type instead of membership, Checking type instead of interface): проверка того, что объект имеет специфический тип, в то время когда требуется только определенный интерфейс.
  • • Инерция кода (Code momentum): сверхограничение части системы путем постоянного подразумевания ее поведения в других частях системы.
  • • Кодирование путем исключения (Coding by exception): добавление нового кода для поддержки каждого специального распознанного случая.
  • • Таинственный код (Cryptic code): использование аббревиатур вместо мнемоничных имен.
  • • Жесткое кодирование (Hard code): внедрение предположений об окружении системы в слишком большом количестве точек ее реализации.
  • • Мягкое кодирование (Soft code): патологическая боязнь жесткого кодирования, приводящая к тому, что настраивается все что угодно, при этом конфигурирование системы само по себе превращается в программирование.
  • • Поток лавы (Lava flow): сохранение нежелательного (излишнего или низкокачественного) кода по причине того, что его удаление слишком дорого или будет иметь непредсказуемые последствия.
  • • Волшебные числа (Magic numbers): включение в алгоритмы чисел без объяснений их смысла.
  • • Процедурный код (Procedural code): когда другая парадигма является более подходящей.
  • • Спагетти-код (Spaghetti code, иногда «макароны»): код с чрезмерно запутанным порядком выполнения.
  • • Лазанья-код (Lasagnia code, или «лук» (onion)): использование неоправданно большого количества уровней абстракции.
  • • Равиоли-код (Ravioli code, или «пельмени»): объекты настолько «склеены» между собой, что практически не допускают рефакторинга.
  • • Мыльный пузырь (Soap bubble): объект, инициализированный мусором, максимально долго притворяется, что содержит какие-то данные.
  • • Мютексный ад (Mutex hell): внедрение слишком большого количества объектов синхронизации между потоками.
  • • Сохранение или смерть (Save or die): сохранение изменений конфигурации на жесткий диск лишь при завершении приложения; приводит к тому, что в случае отказа в программе эти данные будут утеряны.

Методологические антипаттерны:

  • • Программирование методом копирования-вставки (Copy and paste programming): копирование (и легкая модификация) существующего кода вместо создания общих решений.
  • • Золотой молоток (Golden hammer): сильная уверенность в том, что любимое решение универсально применимо. Название происходит от поговорки «когда в руках молоток, все проблемы кажутся гвоздями».
  • • Фактор невероятности (Improbability factor): предположение о невозможности того, что сработает известная ошибка.
  • • Преждевременная оптимизация (Premature optimization): оптимизация на основе недостаточной информации.
  • • Изобретение колеса/велосипеда (Reinventing the wheel): создание с нуля вместо использования готового решения.
  • • Изобретение квадратного колеса (Reinventing the square wheel): создание плохого решения, когда существует хорошее известное решение.
  • • Самоуничтожение (Self-destruction): фатальная ошибка либо нестандартное поведение программы, приводящие к отказу в обслуживании, возникшие вследствие другой менее серьезной ошибки. Например, при возникновении ошибки приложение начинает очень быстро и много писать в лог, вследствие чего заканчивается место на жестком диске быстрее, чем это обнаружит мониторинг.
  • • Два тоннеля: вынесение новой функциональности в отдельное приложение вместо расширения уже имеющегося. Чаше всего применяется, когда по каким-либо причинам (в основном при нехватке времени либо нежелании менеджмента) внесение изменений в уже имеющийся код требует больших затрат, чем создание нового. При этом у клиента в конечном итоге работают два приложения, запускаясь одновременно либо попеременно друг из друга.
  • • Коммит-убийца (Commit assasin): внесение отдельных изменений в систему контроля версий без проверки влияния их на другие части системы. Как правило, после подобных коммитов работа коллектива парализуется на время исправления проблем в местах, которые ранее работали безошибочно.

Антипаттерны управления конфигурацией:

• Ад зависимостей (Dependency hell), на платформе Microsoft Windows также называется «DLL-ад», «DLL hell»): разрастание графа взаимных зависимостей программных продуктов и библиотек, приводящее к сложности установки новых и удаления старых продуктов. В сложных случаях различные установленные программные продукты требуют наличия разных версий одной и той же библиотеки. В наиболее сложных случаях один продукт может косвенно потребовать сразу две версии одной и той же библиотеки.

Некоторые организационные антипаттерны:

  • • Аналитический паралич (Analysis paralysis): неоправданно большие затраты на анализ и проектирование. Часто приводит к закрытию проекта до начала его реализации.
  • • Дойная корова (Cash cow): когда при наличии продукта, приносящего выгоду без существенных вложений, не вкладываются средства в развитие и разработку новых продуктов.
  • • Продолжительное устаревание (Continuous obsolescence): выделение непропорционально больших усилий на портирование системы в новые окружения.
  • • Сваливание расходов (Cost migration): перенос расходов на проект к уязвимому отделу или бизнес-партнеру.
  • • Ползущий улучшизм (Creeping featurism): добавление новых улучшений в ущерб суммарному качеству системы.
  • • Разработка комитетом (Design by committee): разработка проекта без централизованного управления либо при некомпетентном руководстве.
  • • Неуемная преданность (Escalation of commitment): продолжение реализации решения после того, как доказана его ошибочность.
  • • Я тебе это говорил (I told you so): игнорирование мнения эксперта.
  • • Управление, основанное на числах (Management by numbers): излишнее внимание к численным показателям, либо имеющим очень косвенное отношение к управляемой системе, либо сложным для получения.
  • • Драконовские меры (Management by perkele): неоправданно жесткий стиль управления.
  • • Управление грибами (Mushroom management): недостаточное информирование работников о выполняемой работе.
  • • Расползание рамок (Scope сгеер): потеря контроля над разрастанием проекта.
  • • Замыкание на продавце (Vendor lock-in): жесткая привязка к поставщику.
  • • Теплое тело (Warm body): человек, чей вклад в проект под сомнением.
  • • Единственный знающий человек (Single head of knowledge, SHOK): когда жизненно важными для проекта сведениями или навыками обладает только один человек в команде; с его уходом работа останавливается.
  • • Рыцарь на белом коне (Knight in shining armor, K ISA): когда на сцене появляется человек, который пытается починить все, не сообщая никому, что он сделал и почему.

Шуточные антипаттерны:

• Паблик Морозов: класс-потомок, созданный в соответствии с этим антипаттерном, выдает по запросу все данные класса-пред-ка независимо от степени их сокрытия. Название данного антипаттерна — это каламбур, основанный на созвучии ключевого слова public (паблик), часто означающего открытый доступ к методам и полям класса в объектно-ориентированных языках программирования, и имени пионера-героя Павлика Морозова, выдавшего, по утверждению советской пропаганды, следственным органам своего отца, имевшего преступные связи с кулаками.

Контрольные вопросы

  • 1. Дайте определение паттерна проектирования.
  • 2. Перечислите основные элементы паттерна пректирования.
  • 3. Перечислите основные категории паттернв пректирования прграммных систем.
  • 4. Каталог паттернов проектирования (боР). Его составляющие.
  • 5. Объясните различие между паттернами уровня классов и паттернами уровня объектов.
  • 6. Проведите сравнительный анализ порождающих паттернов.
  • 7. Поясните назначение структурных паттернов проектирования.
  • 8. Что является первичным для паттернов поведения: поток управления или связи между объектами?
  • 9. Приведите основное отличие паттернов Go Fot архитектурных системных паттернов.
  • 10. Что такое паттерны GRASP?
  • 11. Поясните термин «антипаттерн». Приведите примеры антипаттернов в программировании.
 
< Пред   СОДЕРЖАНИЕ     След >