JavaRush /Курси /Architecture & Logic /Антипатерни

Антипатерни

Architecture & Logic
Рівень 2 , Лекція 2
Відкрита

Знайомство з антипатернами

Антипатерни — повна протилежність патернам. Якщо патерни — це рецепти «як готувати смачно», то антипатерни — це список того, чого робити на кухні категорично не можна, якщо не хочете отруїти гостей.

Частиною практик гарного програмування є саме уникнення антипатернів. Не слід думати, що це суха теорія — це граблі, на які наступав кожен Senior-розробник. Хто поінформований, той озброєний!

Розглянемо класичну п'ятірку антипатернів:

  • Магічні числа та рядки
  • Божественний об'єкт (God Object)
  • Передчасна оптимізація
  • Винайдення велосипеда
  • Винайдення квадратного колеса

Магічні числа та рядки

Магічне число — це константа (число або рядок), яка зустрічається в коді без пояснення її значення.

if user.status == 2: # Що таке 2? Адмін? Забанений? Мертвий?
    do_something()

Коли в коді з'являються такі числа, програміст, який читатиме цей код за місяць (навіть якщо це ви самі), витратить години, намагаючись зрозуміти цей сакральний зміст.

Як лікувати в Python:

  • Використовуйте константи зі зрозумілими іменами (у верхньому регістрі): STATUS_BANNED = 2.
  • Використовуйте Enums (модуль enum), який з'явився у Python 3.4. Це ідеальне рішення для статусів і типів.

God Object

Божественний об'єкт — це клас, який знає занадто багато, робить занадто багато і зберігає в собі майже всі дані застосунку. У Python цей антипатерн часто мутує в God Module.

Типовий приклад студента — файл views.py або utils.py на 3000 рядків, у якому перемішані:

  • Реєстрація користувачів
  • Відправка email
  • Генерація PDF-звітів
  • Парсинг Excel

Такий код неможливо тестувати (доводиться мокати половину всесвіту), складно читати та страшно змінювати.

Лікування: розбивайте завдання на підзавдання (Single Responsibility Principle). Логіку роботи з поштою — у services/email.py, звіти — у services/reports.py.

Передчасна оптимізація

Передчасна оптимізація — це спроба зробити код швидшим до того, як ви довели, що він працює повільно.

Дональд Кнут сказав: «Передчасна оптимізація — корінь усіх бід».

Пітоністи-початківці часто витрачають години, намагаючись переписати зрозумілий цикл for на складну конструкцію з map/filter/lambda, бо «десь чули, що це швидше». У результаті код стає нечитабельним, а виграш становить 0.001 секунди.

Python-way:

  1. Спочатку пишіть чистий і читабельний код.
  2. Якщо код працює повільно — використовуйте профайлер (модуль cProfile або інструменти в PyCharm).
  3. Знаходьте вузьке місце (часто це зайвий запит до БД, а не Python-код) і оптимізуйте тільки його.

Винайдення велосипеда

Сенс цього антипатерна: програміст пише власне рішення завдання, для якого вже існує готова, перевірена та оптимізована бібліотека.

Python славиться своєю філософією «Батарейки в комплекті» та величезним репозиторієм PyPI.

Приклади «велосипедів»:

  • Писати свій парсер CSV замість import csv.
  • Писати свої регулярні вирази для перевірки email замість використання pydantic.EmailStr.
  • Писати свій клієнт для HTTP-запитів на сокетах замість import requests.

Ваше самописне рішення майже напевно міститиме більше багів і працюватиме повільніше, ніж бібліотека, яку спільнота полірує роками.

Винайдення велосипеда з квадратними колесами

Це посилена версія попереднього пункту. Ви не просто винайшли велосипед, ви винайшли поганий велосипед.

Це подвійна втрата часу: спочатку ви пишете криве рішення, а потім витрачаєте тижні на його лагодження та підтримку. У результаті все одно доводиться викидати код і брати готову бібліотеку.

Dependency Injection

Якщо «God Object» — це хвороба, то Dependency Injection — це ліки. Це патерн, який рятує проєкти від перетворення на «спагеті-код».

Проблема жорсткого зв'язку:

class UserService:
    def __init__(self):
        # ПОМИЛКА: Сервіс сам створює підключення до БД.
        # Тепер ви не зможете протестувати цей сервіс без реальної бази!
        self.db = PostgresDB("localhost", 5432)

Рішення (DI):

class UserService:
    def __init__(self, db):
        # ПРАВИЛЬНО: Залежність (db) передається ззовні.
        # У тестах ви зможете передати сюди «фейкову» базу (Mock).
        self.db = db

Приклад у FastAPI:

Якщо ви працювали з FastAPI, ви вже використовуєте потужну систему DI. Механізм Depends робить усю брудну роботу за вас:

def read_users(db: Session = Depends(get_db)): ...

Фреймворк сам знайде, як створити підключення до БД, і «впровадить» його у вашу функцію. Це робить код чистим, модульним і таким, що легко тестується.

Хронологія технологій

Щоб ви розуміли масштаб досвіду, на який спираєтеся:

  • Мови та стандарти:
    • SQL — 52 роки (1974)
    • Python — 35 років (1991)
    • HTTP — 35 років (1991)
    • Java — 31 рік (1995)
  • Інструменти Python-розробника:
    • Django — 21 рік (2005)
    • SQLAlchemy — 20 років (2006)
    • Git — 21 рік (2005)
    • Docker — 13 років (2013)
    • FastAPI — 7 років (2018)
  • Операційні системи:
    • Unix — 57 років (1969)
    • Linux — 35 років (1991)

Коли вам здається, що ви придумали «унікальну» архітектуру для зберігання налаштувань або роботи з БД — скоріш за все, ви просто не дочитали документацію до інструмента, якому вже 20 років.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ