С какими антипаттернами в коде и архитектуре вы сталкивались в своих проектах?

«С какими антипаттернами в коде и архитектуре вы сталкивались в своих проектах?» — вопрос из категории Паттерны, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В работе с legacy-системами и при ревью кода часто встречал следующие антипаттерны:

  1. God Object / Божественный объект: Класс, который знает и делает слишком много, нарушая принцип единственной ответственности (SRP). Например, класс Order, который отвечает за расчет стоимости, валидацию, сохранение в БД, отправку email и генерацию PDF.

    • Решение: Разделить на отдельные сервисы: OrderCalculator, OrderValidator, OrderRepository, OrderNotificationService.
  2. Spaghetti Code / Спагетти-код: Полное отсутствие структуры, длинные методы (500+ строк), глобальные переменные, бесконечные цепочки вызовов. Характерно для старых PHP-скриптов.

    • Решение: Постепенный рефакторинг: выделение методов, внедрение классов, следование PSR-стандартам.
  3. Magic Numbers и Hardcode: Использование "магических" чисел и строк прямо в бизнес-логике, что делает код нечитаемым.

    // Антипаттерн
    if ($user->status == 1) { /* ... */ }
    
    // Решение
    class UserStatus {
        public const ACTIVE = 1;
        public const INACTIVE = 2;
        public const BANNED = 3;
    }
    if ($user->status == UserStatus::ACTIVE) { /* ... */ }
  4. Copy-Paste Programming: Дублирование одного и того же кода в нескольких местах. При изменении логики нужно править все копии, что ведет к ошибкам.

    • Решение: Вынесение общей логики в методы-хелперы, трейты или базовые классы.
  5. Premature Optimization / Преждевременная оптимизация: Попытка оптимизировать код (например, использовать сложные структуры данных) до того, как выявлены реальные узкие места через профайлинг.

    • Решение: Следовать принципу "сначала работающий и понятный код, потом оптимизация по мере необходимости".
  6. Circular Dependency / Циклическая зависимость: Когда класс А зависит от класса Б, а класс Б зависит от класса А. Это ломает компоновку, усложняет тестирование.

    • Решение: Внедрение паттерна Mediator, использование событий (Event-Driven) или пересмотр архитектуры для разрыва цикла.
  7. Shotgun Surgery / Выстрел дробью: Когда одно изменение требует правок во множестве классов. Признак плохой связности.

    • Решение: Рефакторинг для улучшения инкапсуляции, возможно, применение паттерна Facade.
  8. Ignoring Errors / Игнорирование ошибок: Глобальное подавление ошибок оператором @ или пустые блоки catch.

    // Плохо
    $data = @file_get_contents('unreliable_source.json');
    // Хорошо
    try {
        $data = file_get_contents('source.json');
        if ($data === false) { throw new IOException('Failed to read file'); }
    } catch (IOException $e) {
        // Логируем ошибку и предпринимаем осмысленное действие
        $this->logger->error($e->getMessage());
        $data = $this->getFallbackData();
    }

Борьба с этими антипаттернами — постоянная часть работы senior-разработчика, направленная на поддержание качества и поддерживаемости кодовой базы.