Антипатерн
Антипа́терн, або антишабло́н — загальний спосіб вирішення проблеми, що часто виникає під час проєктування програмного забезпечення, який, як правило, неефективний та зменшує продуктивність комп'ютерної програми. Інакше кажучи, антипатерн — шкідливий і неефективний патерн.
Концепція антипатерну є універсальною і придатна не лише для програмної інженерії, але й для практично будь-якої сфери людської діяльності; втім, термін не набув поширення поза межами IT-індустрії.
Поняття антипатерну з'явилось тоді, коли програмісти зрозуміли, що описувати і документувати необхідно не лише гарні ідеї, але й погані. Правильно сформульований антипатерн складається не лише з опису типової помилки, але й пояснює, чому таке рішення виглядає привабливим (наприклад, економить час розробки, чи дійсно працює в деякому обмеженому контексті), до яких негативних наслідків воно призводить, і яким патерном бажано його замінити.
Найважливіша мета документації антипатернів — полегшити можливість розпізнавання шкідливого рішення і успішного виправлення помилок ще на ранніх етапах роботи[1]. Антипатерн не просто застерігає «Не роби цього!», а вказує інженеру на те, що він, можливо, не усвідомлює, що рішення такого типу принесе набагато більше шкоди, ніж користі.
Існує 3 ключових правила, коли рішення вважається антипатерном:
- Загальноприйнятий процес, структура чи план дій, який на перший погляд дає ефективне рішення, найчастіше дає більше негативних наслідків, ніж позитивних.
- Цей процес (структура, план), незважаючи на свою шкідливість, достатньо поширений на практиці.
- Правильне рішення вже існує, воно задокументовано та перевірено на ефективність.
Історія
З розвитком ІТ-індустрії масштаби програмних проєктів та витрати ресурсів на них нестримно росли, що породжувало велику кількість проблем, що поставали перед програмістами. Більшість цих проблем були типовими і зустрічались практично в кожному великому проєкті. На початку 90-х років набули значної популярності каталоги шаблонів проєктування (англ. design patterns) — елегантних і перевірених на практиці способів вирішення типових проблем. Патерни і на сьогоднішній день є потужними і надзвичайно популярними, проте багато розробників, використовуючи популярні патерни в ситуаціях, до яких вони не пристосовані, робили програми вкрай неефективними, чи породжували набагато більше проблем, ніж було в проєкті перед використанням патерну. Крім того, у ІТ-інженерів, як і у працівників будь-якої сфери діяльності, можна виокремити типові помилки, зумовлені недостатньою базою знань чи відсутністю досвіду в програміста, стислими термінами здачі проєкту, фінансовими обмеженнями та іншим.
Вперше термін «Антипатерн» в розумінні формальної моделі типового невдалого рішення використовується 1996 року Майклом Ейкройдом (англ. Michael Akroyd) на конференції «Object World West Conference», посвяченій аспектам об'єктно-орієнтованого програмування[1]. У своїй презентації «Антипатерни: запобігання неправильному використанню об'єктів», Ейкройд звертав увагу на шкідливі, але часті програмні конструкції, зокрема, ті, що суперечать принципам ООП. До того ж, для кожної такої конструкції він пропонував ефективну заміну.
Термін (в розумінні: «погана ідея») зустрічався і до Ейкройда, але не публікувався і особливою популярністю не користувався. Та все ж, приписувати авторство одній людині не варто. Як вважає Вільям Браун, автор книги «Антипатерни: рефакторинг програм, архітектур та проєктів», антипатерн — це етап еволюції поняття патерну проєктування, розширення їх моделі.
Приклади
Організаційні
- Паралізоване мислення (Analysis paralysis): Проєкт зупиняється на стадії аналізу та специфікацій, які менеджмент хоче виконати якнайкраще.
- Велосипедний навіс (Bicycle shed): Надання великого значення неважливим питанням. Походить від історії обговорень будівництва ядерної електростанції, коли більше уваги приділялося деталям навісу для велосипедів, а не самій станції.
- Вбивча технологія (Bleeding edge): Ризик застосування технології, яка ще не пройшла належного випробування. В результаті такя технологія може призвести до надвитрат, низьких результатів, відкладення термінів завершення проєкту. Походить від алюзії подібних термінів leading edge / cutting edge.
- Ефект свідка (Bystander apathy): Феномен, коли ймовірність допомоги людині в біді від свідків знижується пропорційно кількості свідків. Всі вважають, що допомогти має хтось інший.
- Дійна корова (Cash cow): Негативний вплив історії успішного продукту на незадоволеність новими продуктами, які ще розвиваються.
- Дизайн від комітету (Design by committee): Участь багатьох в обговоренні та прийнятті рішень щодо дизайну, що призводить до розмитого бачення продукту / дизайну.
- Ескалація прив'язаності (Escalation of commitment): Відмова й неможливість скасувати попереднє неправильне рішення. Походить від феномену названого оманою неповоротних витрат.
- Групове/стадне мислення (Groupthink): Прийняття думки одного учасника групи як основної та небажання брати до уваги думки інших учасників.
- Управління за цілями (Management by objectives): Надмірне значення надається цифрам, які не мають значення для проєкту або отримання цих даних коштує високу ціну.
- Мікроменеджмент (Micromanagement): Зловживання контролем в управлінні підлеглими.
- Моральний ризик (Moral hazard): Ізоляція людини, що приймає рішення, від наслідків її / його рішення.
- Грибне управління (Mushroom management): Викривлені комунікації між управлінцем і працівниками, коли працівникам надається тільки обмежена інформація («ростуть у темряві, харчуються навозом»).
- Принцип Пітера (Peter principle): Просування працівників вище по кар'єрній драбині, засноване на поточних показниках, а не їх здатності розвиватися на новій посаді. В результаті такого успішний працівник не справляється із новим завданням / посадою.
- Чайка-менеджмент (Seagull management): Керівник звертається до працівників лише, коли виникає проблема, перед здачею роботи, або просто «прибігає, багато галасує, не вирішує проблему й зникає».
- Силос (Stovepipe або Silos): Створення структури із малих розрізнених команд, які працюють кожна над своїм завданням і їх результати роботи неможливо поєднати.
- Рольове кліше (Typecasting): Доручення одноманітних завдань спеціалісту, який успішний в певному питанні. Але обмеження його/її розвитку.
- Залежність від постачальника (Vendor lock-in): Створення системи надмірно залежної від одного постачальника, якого неможливо або важко замінити.
Антипатерни проєктування програмного забезпечення
- Інверсія абстракції (Abstraction inversion) — приховування частини функціональності від зовнішнього використання, в надії на те, що ніхто не буде її використовувати.
- Неоднозначна точка зору (Ambiguous viewpoint) — представлення моделі без специфікації її точки розгляду.
- Database-as-IPC: Використання бази даних, як черги повідомлень для рутинних внутрішніх комунікацій, коли можна застосувати більш простіший механізм, наприклад сокети.
- Золоте покриття (Gold plating): Продовження роботи над завданням чи проєктом, коли вартість роботи перевищує вигоду від її ефективності.
- Внутрішньоплатформний ефект (Inner-platform effect): Система може так налаштовуватися, що стає бідною копією середовища розробки.
- Ляп на вході: Неможливість визначити і реалізувати обробку помилки через неправильні вхідні дані.
- Перевантажений інтерфейс: Проєктування настільки складного інтерфейсу, що його вкрай важко реалізовувати.
- Магічна кнопка (Magic pushbutton): Кодування логіки реалізації класу безпосередньо в коді елементів інтерфейсу, без використання абстракції.
- Стан гонитви (Race hazard): Результат програми залежить від послідовності неконтрольованих подій.
- Димохід (Stovepipe system): Легкий супровід збірки погано зв'язаних елементів.
Антипатерни програмування
- Зайва складність (Accidental complexity): Представлення необов'язкової складності в програмі.
- Дії на відстані (Action at a distance): Неочікувана взаємодія між ізольованими частинами програми.
- Сліпа віра (Blind faith): Не перевірка, виправлення помилки, чи результату підпрограми
- П'яте колесо (Boat anchor): Зберігання частин коду, що не використовуються.
- Холостий цикл (Busy waiting): Використання CPU під час очікування якоїсь дії, зазвичай для тривалих циклів перевірки, замість використання повідомлень подій.
- Кеш відмов (Caching failure): Забування скинути прапорець помилки після її виправлення.
- Карго-культ програмування (Cargo cult programming): Використання патернів та методів без розуміння мети.
- Кодування виключень (Coding by exception): Додавання нового коду для обробки кожної виняткової ситуації.
- Приховування помилок (Error hiding): Перехоплення повідомлень, що свідчать про помилку, до того, як вони надійдуть до користувача, замість реального виправлення помилок.
- Жорсткий код (Hard code): Вкладення припущень про середовище системи у її реалізації.
- М'який код (Soft code): Зберігання бізнес-логіки у конфігураційних файлах, а не у коді.
- Послідовність циклів-розгалужень (Loop-switch sequence): Кодування послідовності кроків використовуючи розгалуження всередині циклів.
- Магічні числа (Magic numbers): Включення непрокоментованих та незадокументованих констант до алгоритму.
- Повторення коду (Repeating yourself): Написання коду, який повторюється знову і знову, замість організації підпрограм.
- Код-спагеті (Spaghetti code): Програми, структури яких ледь зрозумілі через неправильне застосування структур коду.
- Лазанья-код (Lasagna code): Програма, структура якої містить забагато рівнів.
Антипатерни об'єктно-орієнтованого програмування
- BaseBean: Спадкування функціональності зі службового класу, а не делегування йому вирішення проблем.
- Супер виклик (Call super): Обов'язкові підкласи для виклику перевизначеного методу суперкласу.
- Проблема коло-еліпс (Circle-ellipse problem): Використання підтипу змінної-типу чи базового підтипу-значення.
- Кільцеві залежності (Circular dependency): Представлення непотрібних прямих чи непрямих взаємних залежностей між об'єктами та модулями програми.
- Інтерфейс констант (Constant interface): Використання інтерфейсів для визначення констант.
- Божественний об'єкт (God object): Концентрування функціоналу в одній частині проєкту (класу, методі).
- Об'єкт вигрібної ями (Object cesspool): Повторне використання об'єкту, стан якого не допускає повторне використання.
- Об'єкт оргії (Object orgy): Неможливість інкапсулювати об'єкти належним чином дає необмежений доступ до його внутрішніх функцій.
- Полтергейсти (Poltergeists): Об'єкти, єдиною метою яких є передача інформації на інші об'єкти.
- Послідовне з'єднання (Sequential coupling): Клас вимагає, щоб його методи викликалися у певному порядку.
- Проблема Йо-йо (Yo-yo problem): Структуру (наприклад, наслідування), важко зрозуміти через надмірну фрагментацію.
Антипатерни методологій програмування
- Програмування методом копіювання-вставлення (Copy and paste programming): Копіювання (і зміна) наявного коду, замість того, щоб створювати нове рішення.
- Золотий молоток (Golden hammer): Припущення, що улюблене рішення є універсальним.
- Коефіцієнт неймовірності (Improbability factor): Припущення, що ймовірність виникнення помилки є достатньо низькою.
- Це придумав не я (Not Invented Here (NIH) syndrome): Обвинувачення колишніх співробітників організації в написанні непрацюючого коду.
- Це придумав я (Invented Here): Тенденція до несприйняття нових чи менш тривіальних рішень всередині організації, найчастіше через недовіру до персоналу.
- Передчасна оптимізація (Premature optimization): Завчасне програмування для підвищення ефективності, жертвуючи хорошим дизайном, гнучкістю, а інколи навіть реальною ефективністю.
- Програмування перестановкою (або «випадкове програмування»), або «програмування за збігом обставин») (Programming by permutation (or «programming by accident», or «programming by coincidence»)): Спроба знайти рішення шляхом послідовної зміни коду і перевіряючи «чи воно працює».
- Винаходження велосипеда (Reinventing the square Wheel): При не змозі використати наявне рішення, намагаєшся оптимізувати своє, яке працює набагато гірше.
- Срібна куля (Silver bullet): Припущення, що улюбленим технічним рішенням можна вирішити більшу проблему.
- Tester Driven Development: програмні проєкти, в яких нові вимоги зазначені в повідомленнях про помилки.
Антипатерни системного адміністрування
- Пекло залежностей (англ. Dependency hell): Залежність від версій необхідних бібліотек і програм. Поширений в Unix-середовищах.
- DLL пекло (DLL hell): Неадекватне управління динамічними бібліотеками (DLLs). Поширений в Microsoft Windows.
Див. також
Примітки
Література
- Brown, William J.; Raphael C. Malveau, Hays W. "Skip" McCormick, Thomas J. Mowbray, Theresa Hudson (ed) (1998). AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis. John Wiley & Sons, ltd. ISBN 978-0-471-19713-3.