Техники рефакторинга
Рефакторинг — улучшение структуры кода без изменения его поведения. Снаружи программа делает то же самое, внутри — стала чище. Главное правило: рефакторинг безопасен только когда есть тесты, которые подтверждают, что поведение не сломалось (см. тему «Пирамида тестов»).
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-го слоя).