На какие ключевые аспекты ты обращаешь внимание при рефакторинге класса?

«На какие ключевые аспекты ты обращаешь внимание при рефакторинге класса?» — вопрос из категории Архитектура, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Рефакторинг направлен на улучшение внутренней структуры кода без изменения внешнего поведения. Ключевые аспекты:

1. Принцип единственной ответственности (SRP):

  • Класс должен иметь одну причину для изменения.
  • Действие: Выделите отдельные классы для несвязанных обязанностей (логика, валидация, преобразование данных).

2. Читаемость и простота:

  • Имена: Методы и переменные должны явно отражать свою цель (calculateTotalPrice() вместо calc()).
  • Длина методов: Стремитесь к методам не длиннее 10-20 строк.
  • Уровень абстракции: Метод должен работать на одном уровне (не смешивать высокоуровневую логику с деталями реализации).

3. Избавление от дублирования (DRY):

  • Повторяющийся код — источник будущих ошибок. Вынесите его в приватные методы или утилитные классы.

4. Связность и зацепление:

  • Высокая связность: Элементы класса тесно связаны по смыслу.
  • Слабое зацепление: Класс минимально зависит от других классов (используйте интерфейсы, Dependency Injection).

5. Обработка ошибок:

  • Используйте специфичные исключения вместо общих.
  • Проверяйте предварительные условия (валидация входных данных).

Пример рефакторинга:

// ДО: Длинный метод со смешанной логикой
public void processOrder(Order order) {
    if (order == null || order.getItems().isEmpty()) {
        System.out.println("Invalid order"); // Плохо: прямая печать
        return;
    }
    // ... 30 строк логики расчета и сохранения
}

// ПОСЛЕ:
public void processOrder(Order order) throws InvalidOrderException {
    validateOrder(order); // SRP: валидация выделена
    double total = calculateTotal(order); // SRP: расчет выделен
    saveOrder(order, total); // SRP: сохранение выделено
}

private void validateOrder(Order order) throws InvalidOrderException {
    if (order == null || order.getItems().isEmpty()) {
        throw new InvalidOrderException("Order must contain items."); // Явное исключение
    }
}