Информационные списки

Антипаттерн

Материал из Википедии — свободной энциклопедии
Перейти к: навигация, поиск

Антипаттерн (англ. anti-pattern) — это распространённый подход к решению класса часто встречающихся проблем, являющийся неэффективным, рискованным или непродуктивным[1]. В отличие от шаблона проектирования, рассмотрение антипаттерна включает в себя как неправильное решение проблемы с его признаками и последствиями, так и выход из ситуации[2].

Термин происходит из информатики, из книги «Банды четырёх» «Шаблоны проектирования», которая заложила примеры практики хорошего программирования. Авторы назвали эти хорошие методы «паттернами», и противоположными им являются «антипаттерны». Частью хорошей практики программирования является избегание антипаттернов. До появления термина все проблемы назывались ловушки (pitfalls). Таким образом, антипаттерны — это самые распространённые ловушки, но не все ловушки будут антипаттернами.

Антипаттерны концептуально похожи на паттерны в том, что они документируют повторяющиеся решения общих проблем. Они известны как антипаттерны, потому что их использование (или злоупотребления) даёт негативные последствия[3].

Концепция также прекрасно подходит к машиностроению. Несмотря на то, что термин нечасто используется вне программной инженерии, концепция является универсальной.

Антипаттерн и паттерн ошибки[править | править вики-текст]

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

В отличие от паттернов ошибок, антипаттерны относятся к уровню проектирования, а не кодирования.

Антипаттерны являются паттернами проектирования, паттерны ошибок представляют собой паттерны некорректного поведения программ, коррелирующего с ошибками программирования[4].

История[править | править вики-текст]

С развитием ИТ-индустрии масштабы программных проектов и затраты ресурсов на них стремительно росли, что порождало большое количество проблем, что вставали перед программистами. Большинство этих проблем были типичными и встречались практически в каждом крупном проекте. В начале 90-х годов приобрели значительной популярности каталоги шаблонов проектирования (англ. design patterns) — элегантных и проверенных на практике способов решения типичных проблем. Паттерны и на сегодняшний день являются мощными и чрезвычайно популярны, однако многие разработчики, используя популярные паттерны в ситуациях, к которым они не приспособлены, делали программы крайне неэффективными, порождали гораздо больше проблем, чем было в проекте перед использованием паттерна. Кроме того, у ИТ-инженеров, как и у работников любой сферы деятельности, можно выделить типичные ошибки, обусловленные недостаточной базой знаний или отсутствием опыта у программиста, сжатыми сроками сдачи проекта, финансовыми ограничениями и прочим.

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

Термин (в смысле: «плохая идея») встречался и до Эйкройда, но не публиковался и особой популярностью не пользовался. И все же, приписывать авторство одному человеку не стоит. Как считает Уильям Браун, автор книги «Антипаттерны: рефакторинг приложений, архитектур и проектов», антипаттерн — это этап эволюции понятия паттерна проектирования, расширения их модели.

Классификация[править | править вики-текст]

Уильям Браун выделяет антипаттерны с трёх точек зрения: разработчика, архитектора и менеджера:

  • Антипаттерны разработки (development antipatterns)[⇨]
  • Архитектурные антипаттерны (architectural antipatterns)[⇨]
  • Организационные антипаттерны (managerial antipatterns)[⇨]

Нейл и Лаплантэ приводят четвёртый тип[6][7]:

  • Антипаттерны среды (environmental antipatterns)[⇨]

Кроме того, антипаттерны были описаны для отдельных информационных технологий, таких как[7]:

Антипаттерны разработки[править | править вики-текст]

Технические проблемы и решения, с которыми имеют дело программисты[7]:

Антипаттерны в объектно-ориентированном программировании[править | править вики-текст]

  • Базовый класс-утилита (BaseBean[13]): Наследование функциональности из класса-утилиты вместо делегирования к нему
  • Anemic Domain Model[13] — боязнь размещать логику в объектах предметной области.
  • Вызов предка (Call super): Для реализации прикладной функциональности методу класса-потомка требуется в обязательном порядке вызывать те же методы класса-предка
  • Ошибка пустого подкласса (Empty subclass failure): Создание класса (в Perl), который не проходит «проверку пустоты подкласса» («Empty Subclass Test») из-за различного поведения по сравнению с классом, который наследуется от него без изменений
  • Божественный объект (God object): Концентрация слишком большого количества функций в одной части системы (классе)
  • Объектная клоака (Object cesspool): Переиспользование объектов, находящихся в непригодном для переиспользования состоянии
  • Полтергейст (Poltergeist[14]): Объекты, чьё единственное предназначение — передавать информацию другим объектам
  • Проблема йо-йо (Yo-yo problem): Чрезмерная размытость сильно связанного кода (например, выполняемого по порядку) по иерархии классов.
  • Одиночество (Singletonitis): Неуместное использование паттерна одиночка
  • Приватизация (Privatisation): Сокрытие функциональности в приватной секции (private), что затрудняет его расширение в классах-потомках
  • Френд-зона (Friend zone): Неуместное использование дружественных классов и дружественных функций в языке C++
  • Каша из интерфейсов (Interface soup[15]): Объединение нескольких интерфейсов, разделенных согласно принципу изоляции интерфейсов (Interface segregation), в один
  • Висящие концы: Интерфейс, большинство методов которого бессмысленны и реализуются «пустышками»
  • Заглушка (Stub): Попытка «натянуть» на объект уже имеющийся малоподходящий по смыслу интерфейс, вместо создания нового

Антипаттерны в кодировании[править | править вики-текст]

  • Ненужная сложность[en] (Accidental complexity): Внесение ненужной сложности в решение
  • Действие на расстоянии[en] (Action at a distance): Неожиданное взаимодействие между широко разделёнными частями системы
  • Накопить и запустить (Accumulate and fire): Установка параметров подпрограмм в наборе глобальных переменных
  • Слепая вера[en] (Blind faith): Недостаточная проверка корректности исправления ошибки или результата работы подпрограммы
  • Лодочный якорь[en] (Boat anchor)[14]: Сохранение более не используемой части системы
  • Активное ожидание[en] (Busy spin, busy waiting): Потребление ресурсов ЦПУ (процессорного времени) во время ожидания события, обычно при помощи постоянно повторяемой проверки, вместо того, чтобы использовать асинхронное программирование (к примеру, систему сообщений или событий)
  • Кэширование ошибки[en] (Caching failure): Забывать сбросить флаг ошибки после её обработки
  • Воняющий подгузник (The Diaper Pattern Stinks): Сброс флага ошибки без её обработки или передачи вышестоящему обработчику
  • Проверка типа вместо интерфейса (Checking type instead of membership, Checking type instead of interface): Проверка того, что объект имеет специфический тип в то время, когда требуется только определённый интерфейс
  • Инерция кода (Code momentum): Сверхограничение части системы путём постоянного подразумевания её поведения в других частях системы
  • Кодирование путём исключения[en] (Coding by exception): Добавление нового кода для поддержки каждого специального распознанного случая
  • Таинственный код (Cryptic code): Использование аббревиатур вместо мнемоничных имён
  • Жёсткое кодирование (Hard code): Внедрение предположений об окружении системы в слишком большом количестве точек её реализации
  • Мягкое кодирование (Soft code): Патологическая боязнь жёсткого кодирования, приводящая к тому, что настраивается всё что угодно, при этом конфигурирование системы само по себе превращается в программирование
  • Поток лавы[en] (Lava flow)[14]: Сохранение нежелательного (излишнего или низкокачественного) кода по причине того, что его удаление слишком дорого или будет иметь непредсказуемые последствия
  • Волшебные числа (Magic numbers): Использование числовых констант без объяснения их смысла
  • Процедурный код (Procedural code): Когда другая парадигма является более подходящей
  • Спагетти-код (Spaghetti code, иногда «макароны»)[14]: Код с чрезмерно запутанным порядком выполнения
  • Лазанья-код (Lasagnia code, или «лук» (onion)): Использование неоправданно большого количества уровней абстракции
  • Равиоли-код (Ravioli code, или «пельмени»): Объекты настолько «склеены» между собой, что практически не допускают рефакторинга
  • Мыльный пузырь (Soap bubble): Объект, инициализированый мусором, максимально долго притворяется, что содержит какие-то данные
  • Мьютексный ад (Mutex hell): Внедрение слишком большого количества объектов синхронизации между потоками
  • (Мета-)шаблонный рак (Template cancer): Повсеместное использование шаблонов (в основном C++), в том числе там, где их использование не оправдано. Это уменьшает понимание и сопровождение кода и замедляет компиляцию.

Методологические антипаттерны[править | править вики-текст]

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

Антипаттерны управления конфигурацией[править | править вики-текст]

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

Разные[править | править вики-текст]

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

Архитектурные антипаттерны[править | править вики-текст]

Типичные проблемы, связанные со структурой системы[7]:

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

Организационные антипаттерны[править | править вики-текст]

Проблемы, с которыми встречаются менеджеры (или группы менеджеров)[7]:

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

Нейл и Лапланте приводят следующие антипаттерны[6]:

  • (Absentee Manager)
  • (All You Have Is A Hammer)
  • (Cage Match Negotiator)
  • (Doppelganger)
  • (Fruitless Hoops)
  • (Golden Child)
  • (Headless Chicken)
  • (Leader Not Manager)
  • (Managerial Cloning)
  • (Manager Not Leader)
  • (Metric Abuse)
  • (Mr. Nice Guy)
  • (Mushroom Management)
  • (Plate Spinning)
  • (Proletariat Hero)
  • (Rising Upstart)
  • (Road to Nowhere)
  • (Spineless Executive)
  • (Three-Headed Knight)
  • (Ultimate Weapon)
  • (Warm Bodies)

Антипаттерны среды[править | править вики-текст]

Проблемы, вызванные доминирующей в организации структурой и социальной моделью, являющейся результатом действующей в организации общественной политики[17][7][6][18]:

См. также[править | править вики-текст]

Примечания[править | править вики-текст]

  1. Budgen, D. Software design. — Addison-Wesley, 2003. — ISBN 0-201-72219-4.
  2. Brown, 1998.
  3. Smith C.U., 2000.
  4. 1 2 Аллен Э., 2003, с. 65—66.
  5. http://c2.com/cgi/wiki?AntiPattern. Cunningham & Cunningham, Inc..
  6. 1 2 3 Neill, Laplante, 2005.
  7. 1 2 3 4 5 6 settas, 2011.
  8. Miroslav Kis. Information security antipatterns in software requirements engineering. In Proceedings of the 9th Conference on Pattern Language of Programs (Plop), 2002.
  9. John Long. Software reuse antipatterns. In ACM SIGSOFT Software Engineering Notes, volume26, page 4, July 2001.
  10. Paula Kotze, Karen Renaud, and Judy van Biljona. Don’t do this — pitfalls in using anti-patterns in teaching human-computer interaction principles. Computers and Education, 50(3):979-1008, April 2008
  11. J. Krai and M. Zemlicka. The most important service-oriented antipatterns. In proceedings of the International Conference on Software Engineering Advances (ICSEA), 2007.
  12. P.A. Laplante, R.R. Hoffman, and G. Klein. Antipatterns in the creation of intelligent systems. IEEE Intelligent Systems, 22:91-95, 2007.
  13. 1 2 Rajiv Ramnath, Cheyney Loffing. Beginning IOS Programming For Dummies. — John Wiley & Sons, 2014-04-14. — С. 105. — 470 с. — ISBN 9781118799277.
  14. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 William J. Brown. AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis. — Wiley, 1998-04-03. — 156 с. — ISBN 0−471−19713−0.
  15. Gary McLean Hall. Adaptive Code via C#: Agile coding with design patterns and SOLID principles. — Microsoft Press, 2014. — С. 267-268. — ISBN 978-0735683204.
  16. Revenge of the Nerds. — «In the OO world you hear a good deal about "patterns". I wonder if these patterns are not sometimes evidence of case (c), the human compiler, at work. When I see patterns in my programs, I consider it a sign of trouble. The shape of a program should reflect only the problem it needs to solve. Any other regularity in the code is a sign, to me at least, that I'm using abstractions that aren't powerful enough-- often that I'm generating by hand the expansions of some macro that I need to write.»
  17. В оригинале: socio-political forces
  18. Phillip Laplante The Burning Bag of Dung—and Other Environmental Antipatterns ACM Queue November 30, 2004 Volume 2, issue 7

Литература[править | править вики-текст]

Ссылки[править | править вики-текст]