← Назад к вопросам

Что такое антипаттерн?

2.0 Middle🔥 151 комментариев
#SOLID и паттерны проектирования

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Антипаттерн

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

Ключевые характеристики антипаттерна

  • Кажется логичным и простым первоначально
  • Приводит к техническому долгу и сложностям
  • Повторяется во многих кодовых базах
  • Снижает качество, производительность или поддерживаемость кода
  • Со временем стоит всё дороже в поддержке

Классические антипаттерны в Java

1. God Object (Божественный объект)

Один класс отвечает за слишком много функциональности:

// ❌ ПЛОХО: God Object
public class UserManager {
    // Управление пользователями
    public void createUser(User user) { }
    public void deleteUser(Long id) { }
    
    // Управление базой данных
    public void saveToDatabase(User user) { }
    public User getFromDatabase(Long id) { }
    
    // Валидация
    public boolean validateUser(User user) { }
    
    // Email отправка
    public void sendWelcomeEmail(User user) { }
    
    // Логирование
    public void logUserActivity(User user) { }
    
    // Аудит
    public void auditUserChanges(User user) { }
}

// ✅ ХОРОШО: Разделение ответственности
public class UserService {
    private UserRepository repository;
    private EmailService emailService;
    
    public void createUser(User user) {
        repository.save(user);
        emailService.sendWelcomeEmail(user);
    }
}

public class UserRepository {
    public void save(User user) { }
}

public class EmailService {
    public void sendWelcomeEmail(User user) { }
}

2. Circular Dependency (Циклическая зависимость)

Когда классы зависят друг от друга, создавая цикл:

// ❌ ПЛОХО: Циклическая зависимость
public class UserService {
    private OrderService orderService;
    
    public void createUser(User user) {
        orderService.createDefaultOrder(user);
    }
}

public class OrderService {
    private UserService userService;
    
    public void createDefaultOrder(User user) {
        // Вызывает userService где-то, создавая цикл
    }
}

// ✅ ХОРОШО: Использование events или промежуточного сервиса
public class ApplicationService {
    private UserService userService;
    private OrderService orderService;
    
    public void registerNewUser(User user) {
        userService.createUser(user);
        orderService.createDefaultOrder(user);
    }
}

3. Null Pointer Exception Hell (Ад указателей на null)

Постоянная проверка на null, усложняющая код:

// ❌ ПЛОХО: Множество проверок на null
public String getUserCity(User user) {
    if (user != null) {
        Address address = user.getAddress();
        if (address != null) {
            City city = address.getCity();
            if (city != null) {
                return city.getName();
            }
        }
    }
    return "Unknown";
}

// ✅ ХОРОШО: Optional в Java 8+
public String getUserCity(User user) {
    return Optional.ofNullable(user)
        .map(User::getAddress)
        .map(Address::getCity)
        .map(City::getName)
        .orElse("Unknown");
}

4. Magic Numbers & Magic Strings (Магические числа и строки)

Хардкоженные значения без объяснения:

// ❌ ПЛОХО: Магические числа
public class PaymentProcessor {
    public void processPayment(double amount) {
        if (amount < 0 || amount > 99999) {  // Откуда эти числа?
            throw new IllegalArgumentException();
        }
        
        double fee = amount * 0.015;  // Почему 0.015?
        
        if (amount > 1000) {  // Почему 1000?
            applyDiscount();
        }
    }
}

// ✅ ХОРОШО: Константы с понятными именами
public class PaymentProcessor {
    private static final double MIN_PAYMENT = 0;
    private static final double MAX_PAYMENT = 99999;
    private static final double STANDARD_FEE_RATE = 0.015;
    private static final double DISCOUNT_THRESHOLD = 1000;
    
    public void processPayment(double amount) {
        if (amount < MIN_PAYMENT || amount > MAX_PAYMENT) {
            throw new IllegalArgumentException("Invalid amount");
        }
        
        double fee = amount * STANDARD_FEE_RATE;
        
        if (amount > DISCOUNT_THRESHOLD) {
            applyDiscount();
        }
    }
}

5. Spaghetti Code (Спагетти код)

Код с запутанным потоком управления:

// ❌ ПЛОХО: Спагетти логика
public void processOrder(Order order) {
    if (order.getItems().size() > 0) {
        double total = 0;
        for (Item item : order.getItems()) {
            total += item.getPrice();
            if (item.isAvailable()) {
                if (order.getUser().isPremium()) {
                    total *= 0.9;
                    if (item.getCategory().equals("ELECTRONICS")) {
                        total *= 0.95;
                    }
                }
            }
        }
    }
}

// ✅ ХОРОШО: Чистый, понятный код
public void processOrder(Order order) {
    PriceCalculator calculator = new PriceCalculator(order.getUser());
    double total = order.getItems().stream()
        .filter(Item::isAvailable)
        .mapToDouble(item -> calculator.calculatePrice(item))
        .sum();
    order.setTotal(total);
}

6. Copy-Paste Programming (Копипаст программирование)

Дублирование кода вместо рефакторинга:

// ❌ ПЛОХО: Дублирование
public class UserValidator {
    public boolean validateEmail(String email) {
        if (email == null || email.isEmpty()) return false;
        if (!email.contains("@")) return false;
        if (!email.contains(".")) return false;
        return true;
    }
}

public class ProductValidator {
    public boolean validateContactEmail(String email) {
        if (email == null || email.isEmpty()) return false;
        if (!email.contains("@")) return false;
        if (!email.contains(".")) return false;
        return true;
    }
}

// ✅ ХОРОШО: Общий валидатор
public class EmailValidator {
    public boolean validate(String email) {
        if (email == null || email.isEmpty()) return false;
        if (!email.contains("@")) return false;
        if (!email.contains(".")) return false;
        return true;
    }
}

public class UserValidator {
    private EmailValidator emailValidator;
    public boolean validateEmail(String email) {
        return emailValidator.validate(email);
    }
}

7. Premature Optimization (Преждевременная оптимизация)

Оптимизация без доказательства, что это необходимо:

// ❌ ПЛОХО: Оверкомплексная оптимизация
public List<User> getActiveUsers() {
    // Сложная система кэширования, несколько слоёв оптимизации
    // Но профилер показывает, что это узкое место в 0.1% случаев
    return complexCacheLogic();
}

// ✅ ХОРОШО: Сначала просто и понятно
public List<User> getActiveUsers() {
    return users.stream()
        .filter(User::isActive)
        .collect(Collectors.toList());
}
// Если профилер покажет проблемы — тогда оптимизировать

8. Over-Engineering (Переинжиниринг)

Добавление сложности "на будущее":

// ❌ ПЛОХО: Переинжиниринг
public abstract class BaseEntity {
    // 20 методов утилит
    // 15 конфигов
    // 3 слоя абстракций
    // "может пригодиться в будущем"
}

// ✅ ХОРОШО: YAGNI (You Aren't Gonna Need It)
public class User {
    private Long id;
    private String name;
    // Только то, что реально нужно сейчас
}

Почему антипаттерны вредны

  • Снижают производительность — неправильная архитектура
  • Усложняют тестирование — тесты становятся хрупкими
  • Увеличивают время разработки — нужно больше работать с плохим кодом
  • Повышают стоимость поддержки — технический долг растёт
  • Усложняют сотрудничество — новые разработчики не понимают код

Как избежать антипаттернов

  1. Изучайте паттерны проектирования (Design Patterns)
  2. Следуйте SOLID принципам
  3. Пишите чистый код (Clean Code)
  4. Code Review с опытными разработчиками
  5. Рефакторинг — постоянно улучшайте код
  6. Тестирование — покрывайте код тестами
  7. Инструменты анализа (SonarQube, Checkstyle)

Антипаттерны — это учебные материалы, показывающие, как не нужно писать код.

Что такое антипаттерн? | PrepBro