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

Термин происходит из информатики, из книги «Банды четырёх» «Шаблоны проектирования», которая заложила примеры практики хорошего программирования. Авторы назвали эти хорошие методы «паттернами», и противоположными им являются «антипаттерны».

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

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

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

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

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

Антипаттерны разработки () Архитектурные антипаттерны () Организационные антипаттерны ()

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

Антипаттерны среды ()

Кроме того, антипаттерны были описаны для отдельных информационных технологий, таких как: информационная безопасностьMiroslav Kis. Information security antipatterns in software requirements engineering. In Proceedings of the 9th Conference on Pattern Language of Programs (Plop), 2002. повторное использование кодаJohn Long. Software reuse antipatterns. In ACM SIGSOFT Software Engineering Notes, volume26, page 4, July 2001. человеко-компьютерное взаимодействие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 сервис-ориентированная архитектураJ. Krai and M. Zemlicka. The most important service-oriented antipatterns. In proceedings of the International Conference on Software Engineering Advances (ICSEA), 2007. интеллектуальная информационная системаP.A. Laplante, R.R. Hoffman, and G. Klein. Antipatterns in the creation of intelligent systems. IEEE Intelligent Systems, 22:91-95, 2007.

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

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

Антипаттерны при написании кода (Accidental complexity): Внесение ненужной сложности в решение. (Action at a distance): Неожиданное взаимодействие между широко разделёнными частями системы. Накопить и запустить (Accumulate and fire): Установка параметров подпрограмм в наборе глобальных переменных. (Blind faith): Недостаточная проверка корректности исправления ошибки или результата работы подпрограммы. (Boat anchor): Сохранение более не используемой части системы. Активное ожидание (Busy spin, busy waiting): Потребление ресурсов ЦПУ (процессорного времени) во время ожидания события, обычно при помощи постоянно повторяемой проверки, вместо того, чтобы использовать асинхронное программирование (к примеру, систему сообщений или событий). (Caching failure): Забывать сбросить флаг ошибки после её обработки. Воняющий подгузник (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): Внедрение слишком большого количества объектов синхронизации между потоками. (Мета-)шаблонный рак (Template cancer): Повсеместное использование шаблонов (в основном C++), в том числе там, где их использование не оправдано. Это уменьшает понимание и сопровождение кода и замедляет компиляцию.

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

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

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

Архитектурные антипаттерны