Знакомство с анти-паттернами
Анти-паттерны — полная противоположность паттернам. Если паттерны — это рецепты "как готовить вкусно", то анти-паттерны — это список того, чего делать на кухне категорически нельзя, если не хотите отравить гостей.
Частью практик хорошего программирования является именно избежание анти-паттернов. Не надо думать, что это сухая теория — это грабли, на которые наступал каждый 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:
- Сначала пишите чистый и читаемый код.
- Если код работает медленно — используйте профайлер (модуль
cProfileили инструменты в PyCharm). - Находите узкое место (часто это лишний запрос к БД, а не 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 лет.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ