Карта / Чистота кода и рефакторинг / Техники рефакторинга

Техники рефакторинга

Рефакторинг — улучшение структуры кода без изменения его поведения. Снаружи программа делает то же самое, внутри — стала чище. Главное правило: рефакторинг безопасен только когда есть тесты, которые подтверждают, что поведение не сломалось (см. тему «Пирамида тестов»).

Extract Method — вынести кусок кода в отдельный метод с понятным именем:

// до
void processOrder(Order order) {
    if (order.getItems().isEmpty() || order.getTotal() < 0) {
        throw new IllegalArgumentException("Некорректный заказ");
    }
    // ... остальная логика
}

// после
void processOrder(Order order) {
    validate(order);
    // ... остальная логика
}
void validate(Order order) {
    if (order.getItems().isEmpty() || order.getTotal() < 0) {
        throw new IllegalArgumentException("Некорректный заказ");
    }
}

Rename — переименовать переменную/метод/класс, когда текущее имя не отражает суть. IDE делает это безопасно во всём проекте сразу (см. тему «Шорткаты», Shift+F6).

Extract Variable — вынести сложное выражение в переменную с именем:

// до
if (user.getAge() >= 18 && user.hasVerifiedEmail() && !user.isBanned()) { ... }

// после
boolean canVote = user.getAge() >= 18 && user.hasVerifiedEmail() && !user.isBanned();
if (canVote) { ... }
Копнуть глубже

Replace Conditional with Polymorphism — заменить цепочку if-else/switch по типу на разные классы с переопределённым методом (по сути, это и есть паттерн Strategy, см. тему «Поведенческие (Strategy, Observer)»):

// до
double calculatePrice(String type) {
    if (type.equals("standard")) return basePrice;
    if (type.equals("premium")) return basePrice * 1.5;
    if (type.equals("vip")) return basePrice * 2;
    throw new IllegalArgumentException();
}

// после
interface PricingStrategy { double calculate(double basePrice); }
class StandardPricing implements PricingStrategy { ... }
class PremiumPricing implements PricingStrategy { ... }

Главное практическое правило — рефакторинг маленькими безопасными шагами, а не “переписать всё с нуля”. После каждого маленького шага запускаешь тесты — если зелёные, двигаешься дальше; если что-то сломалось, сразу понятно, какой именно шаг это сломал, и можно откатить только его.

Когда рефакторить. Хорошее время — прямо перед тем, как добавлять новую функциональность в код, который и так нужно трогать (“правило бойскаута” из темы «Чистый код — основы»). Плохое время — выделенный отдельный спринт “большой рефакторинг” без чёткой цели: легко увязнуть и не закончить, не принеся реальной пользы бизнесу.

🎤 Закрыл тему, если можешь объяснить:
• что такое рефакторинг и почему он требует тестов;
• техники Extract Method, Rename, Extract Variable, и идею замены if-else на полиморфизм (если дошёл до 2-го слоя).