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

Нужно ли задавать Middle-разработчикам вопросы про Design?

1.0 Junior🔥 11 комментариев
#SOLID и паттерны проектирования#Soft Skills и карьера

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

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

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

Стоит ли задавать Middle разработчикам вопросы о Design Patterns?

Отличный вопрос о уровне подготовки и ожиданиях от кандидатов! Позвольте дать развернутый ответ с разных углов зрения, как интервьюера и как профессионала.

Краткий ответ: ДА, абсолютно нужно

Design Patterns — это неотъемлемая часть компетенций Middle разработчика. Это не "nice to have", а ожидаемый уровень знаний.

Почему Design Patterns важны для Middle?

1. Коммуникация с командой

// Пример обсуждения архитектуры
Senior: "Давай используем Strategy pattern для обработки разных типов платежей"
Middle должен понимать: 
  - Что это Strategy pattern
  - Когда его применять
  - Как его реализовать
  - Плюсы и минусы

2. Проектирование архитектуры

// Middle разработчик должен сам предложить паттерны
public class PaymentProcessing {
    // Правильный подход: Strategy pattern
    private final PaymentStrategy strategy;
    
    public PaymentProcessing(PaymentStrategy strategy) {
        this.strategy = strategy;
    }
    
    public PaymentResult pay(PaymentRequest request) {
        return strategy.process(request);
    }
}

// А НЕ так:
public class BadPaymentProcessing {
    public PaymentResult pay(PaymentRequest request) {
        if (request.getType().equals("CARD")) {
            // обработка карты
        } else if (request.getType().equals("PAYPAL")) {
            // обработка paypal
        } else if (request.getType().equals("CRYPTO")) {
            // обработка крипто
        }
        // ... 50 lines of if-else
    }
}

3. Поддержка кода

Код, написанный с использованием паттернов, проще поддерживать и расширять.

4. Карьерный рост

Необходимо для перехода на Senior/Lead позицию.

Какие паттерны должен знать Middle?

Creational patterns (Порождающие):

// 1. Singleton - один экземпляр
public class ConfigurationManager {
    private static ConfigurationManager instance;
    
    private ConfigurationManager() {}
    
    public static synchronized ConfigurationManager getInstance() {
        if (instance == null) {
            instance = new ConfigurationManager();
        }
        return instance;
    }
}

// 2. Builder - построение сложных объектов
public class UserBuilder {
    private String name;
    private String email;
    private int age;
    
    public UserBuilder withName(String name) {
        this.name = name;
        return this;
    }
    
    public User build() {
        return new User(name, email, age);
    }
}

User user = new UserBuilder()
    .withName("John")
    .withEmail("john@example.com")
    .build();

// 3. Factory - создание объектов
public interface PaymentFactory {
    PaymentProcessor createProcessor(String type);
}

public class PaymentFactoryImpl implements PaymentFactory {
    public PaymentProcessor createProcessor(String type) {
        switch(type) {
            case "CARD": return new CardProcessor();
            case "PAYPAL": return new PayPalProcessor();
            default: throw new IllegalArgumentException();
        }
    }
}

// 4. Prototype - копирование объектов
public class DataSet implements Cloneable {
    public DataSet clone() {
        return (DataSet) super.clone();
    }
}

Structural patterns (Структурные):

// 1. Adapter - адаптация интерфейсов
public class LegacyPaymentAdapter implements PaymentProcessor {
    private LegacyPaymentService legacyService;
    
    @Override
    public PaymentResult process(PaymentRequest request) {
        LegacyRequest legacyRequest = convertRequest(request);
        return convertResult(legacyService.process(legacyRequest));
    }
}

// 2. Decorator - добавление функционала
public class LoggingPaymentDecorator implements PaymentProcessor {
    private PaymentProcessor delegate;
    
    @Override
    public PaymentResult process(PaymentRequest request) {
        logger.info("Processing payment: " + request.getId());
        PaymentResult result = delegate.process(request);
        logger.info("Payment result: " + result);
        return result;
    }
}

// 3. Facade - упрощение сложного интерфейса
public class OrderFacade {
    private PaymentService paymentService;
    private InventoryService inventoryService;
    private NotificationService notificationService;
    
    public void placeOrder(Order order) {
        paymentService.charge(order);
        inventoryService.updateStock(order);
        notificationService.notifyCustomer(order);
    }
}

// 4. Proxy - управление доступом
public class PaymentServiceProxy implements PaymentService {
    private PaymentService realService;
    
    @Override
    public PaymentResult charge(PaymentRequest request) {
        if (!isUserAuthorized()) {
            throw new UnauthorizedException();
        }
        return realService.charge(request);
    }
}

Behavioral patterns (Поведенческие):

// 1. Observer - оповещение об изменениях
public class OrderObserver implements Observer {
    @Override
    public void update(Order order) {
        logger.info("Order updated: " + order.getId());
    }
}

// 2. Strategy - выбор алгоритма
public interface DiscountStrategy {
    double calculate(double price);
}

public class PercentageDiscount implements DiscountStrategy {
    private double percent;
    
    public double calculate(double price) {
        return price * (1 - percent / 100);
    }
}

// 3. Template Method - общий алгоритм
public abstract class PaymentProcessor {
    public final PaymentResult process(PaymentRequest request) {
        validate(request);
        PaymentResult result = charge(request);
        logTransaction(request, result);
        return result;
    }
    
    protected abstract PaymentResult charge(PaymentRequest request);
    protected abstract void validate(PaymentRequest request);
    protected abstract void logTransaction(PaymentRequest req, PaymentResult res);
}

// 4. Command - инкапсуляция операции
public interface Command {
    void execute();
    void undo();
}

public class TransferMoneyCommand implements Command {
    private BankAccount from;
    private BankAccount to;
    private double amount;
    
    @Override
    public void execute() {
        from.withdraw(amount);
        to.deposit(amount);
    }
    
    @Override
    public void undo() {
        to.withdraw(amount);
        from.deposit(amount);
    }
}

// 5. State - изменение поведения
public interface OrderState {
    void process(Order order);
}

public class PendingState implements OrderState {
    @Override
    public void process(Order order) {
        // Process pending order
        order.setState(new ShippingState());
    }
}

Как интервьюировать Middle по Design Patterns?

Вопросы для проверки:

1. "Расскажи про Design Pattern и когда его использовать"
   ✅ Good: Объясняет проблему, решение, примеры, trade-offs
   ❌ Bad: "Это паттерн, который я видел в коде"

2. "У нас есть код с множеством if-else. Что бы ты сделал?"
   ✅ Good: Предлагает Strategy/Factory/Visitor
   ❌ Bad: "Не знаю"

3. "Как добавить логирование ко всем методам класса?"
   ✅ Good: Decorator, AOP, Proxy
   ❌ Bad: Копировать-вставлять код

4. "Какие паттерны ты использовал в реальных проектах?"
   ✅ Good: Конкретные примеры из своего опыта
   ❌ Bad: "Не помню"

Честная шкала для Middle

ОЧЕНЬ ХОРОШИЙ Middle (95-100%):
- Знает 15+ паттернов
- Может объяснить trade-offs
- Применяет паттерны в коде
- Понимает SOLID принципы
- Может refactor код с паттернами

ХОРОШИЙ Middle (80-95%):
- Знает 8-10 основных паттернов
- Может их применять
- Иногда забывает детали
- Нужна помощь с выбором паттерна

СРЕДНИЙ Middle (60-80%):
- Знает 5-7 паттернов
- Может объяснить основные
- Пишет неоптимальный код
- Часто спрашивает совета

СЛАБЫЙ Middle (< 60%):
- Знает названия, но не суть
- Не может применять
- Пишет очень плохой код
- Не развивается

Мое мнение как интервьюера

Да, ОБЯЗАТЕЛЬНО спрашиваю про Design Patterns при интервью Middle разработчика:

Мой процесс:
1. Быстрая проверка (3-5 минут):
   "Расскажи про Factory pattern"
   
2. Практическое задание (20-30 минут):
   "Спроектируй обработку разных типов уведомлений"
   → Проверяю, предложит ли Strategy/Factory
   
3. Код ревью (10-15 минут):
   Показываю плохой код, спрашиваю как улучшить
   → Проверяю знание паттернов
   
4. Его опыт (10-15 минут):
   "Какие паттерны ты использовал?"
   → Проверяю реальный опыт

Связь между уровнями

Junior:
└─ Должен знать: Singleton, Factory, Strategy
   (базовые паттерны)

Middle:
└─ Должен знать: + Decorator, Adapter, Observer, Builder
   (применять в коде, выбирать паттерны)

Senior:
└─ Должен знать: Все + глубокое понимание
   (архитектурные решения, trade-offs)

Lead/Architect:
└─ Должен знать: Все + создавать свои паттерны
   (Domain-Driven Design, микросервисные паттерны)

Выводы

  1. ДА, обязательно спрашиваю про Design Patterns на Middle позицию
  2. Это не опциональное знание, а core competency
  3. Проверяю не только теорию, но и практическое применение
  4. Soft-skilled Middle может не знать все паттерны, но должен:
    • Понимать зачем они нужны
    • Уметь применять основные
    • Быть готовым учиться
  5. Это показатель профессионального развития и амбиций