Refactoring – czysty kod w praktyce

TL;DR

Refactoring to proces poprawy struktury kodu bez zmiany jego funkcjonalności. W tym artykule poznasz podstawowe techniki refactoringu Java, nauczysz się rozpoznawać „zapachy kodu” i zobaczysz praktyczne przykłady transformacji brudnego kodu w czysty, czytelny kod. Idealne dla developerów z 6-18 miesięcy doświadczenia.

Dlaczego refactoring jest kluczowy dla każdego programisty

Wyobraź sobie, że piszesz kod który ma działać przez najbliższe 5 lat. Za pół roku będziesz musiał dodać nową funkcjonalność, za rok – naprawić błąd, a za dwa lata kompletnie przepisać jeden z modułów. Czy będziesz pamiętać co robiłeś w tym kodzie? Czy nowy programista w zespole zrozumie Twoją logikę?

Refactoring to proces systematycznej poprawy struktury kodu bez zmiany jego zewnętrznego zachowania. To jak sprzątanie w domu – nie zmieniasz funkcji pokoju, ale robisz go bardziej funkcjonalnym i przyjaznym dla mieszkańców.

W branży IT szacuje się, że programiści spędzają 80% czasu na czytaniu istniejącego kodu, a tylko 20% na pisaniu nowego. Dlatego czytelność kodu to inwestycja w przyszłość całego zespołu.

Co się nauczysz z tego artykułu

  • Rozpoznawać „zapachy kodu” (code smells) w projektach Java
  • Stosować podstawowe techniki refactoringu: Extract Method, Rename Variable, Extract Constant
  • Bezpiecznie refactorować kod używając IDE IntelliJ IDEA lub Eclipse
  • Rozumieć kiedy refactoring jest konieczny, a kiedy może zaszkodzić
  • Pisać testy jednostkowe jako sieć bezpieczeństwa przed refactoringiem

Wymagania wstępne

Poziom: Podstawy – 6-18 miesięcy programowania w Java

Potrzebujesz: Znajomość podstaw Java (klasy, metody, zmienne), podstawy pracy z IDE (IntelliJ IDEA lub Eclipse), podstawowa znajomość JUnit

Narzędzia: Java 8, IntelliJ IDEA 2016 lub Eclipse Mars, JUnit 4

Czym są „zapachy kodu” i jak je rozpoznać

Code smells to objawy problemów w kodzie – sygnały ostrzegawcze, że coś wymaga poprawy. Nie są to błędy – kod działa, ale jest trudny do zrozumienia, utrzymania lub rozwijania.

Code Smell – symptom głębszego problemu w kodzie. Wskazówka, że kod potrzebuje refactoringu, choć funkcjonalnie działa poprawnie.

Najczęstsze zapachy kodu w Java

1. Długie metody (Long Method)

// PRZED: Długa, nieczytelna metoda
public void processOrder(Order order) {
    // Walidacja - 15 linijek kodu
    if (order == null) throw new IllegalArgumentException("Order cannot be null");
    if (order.getItems().isEmpty()) throw new IllegalArgumentException("Order must have items");
    // ... więcej walidacji
    
    // Kalkulacja ceny - 20 linijek kodu  
    double totalPrice = 0;
    for (OrderItem item : order.getItems()) {
        double itemPrice = item.getPrice();
        if (item.getQuantity() > 10) {
            itemPrice *= 0.9; // 10% rabat
        }
        totalPrice += itemPrice * item.getQuantity();
    }
    
    // Zapis do bazy - 10 linijek kodu
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/shop");
    PreparedStatement ps = conn.prepareStatement("INSERT INTO orders...");
    // ... więcej kodu SQL
}
Pułapka: Metody powyżej 30 linijek są trudne do zrozumienia i testowania. Jeśli nie widzisz całej metody na ekranie – to znak, że trzeba ją podzielić.

2. Magiczne liczby (Magic Numbers)

// PRZED: Magiczne liczby
if (user.getAge() > 65) {
    applyDiscount(0.15);
}

// PO: Wyjaśnione stałe
private static final int SENIOR_AGE_THRESHOLD = 65;
private static final double SENIOR_DISCOUNT_RATE = 0.15;

if (user.getAge() > SENIOR_AGE_THRESHOLD) {
    applyDiscount(SENIOR_DISCOUNT_RATE);
}

Podstawowe techniki refactoringu w praktyce

Extract Method – wyciąganie metod

Najczęściej używana technika. Gdy widzisz fragment kodu który robi coś konkretnego – wyciągnij go do osobnej metody z opisową nazwą.

// PRZED: Wszystko w jednej metodzie
public void processOrder(Order order) {
    // Walidacja
    if (order == null) throw new IllegalArgumentException("Order cannot be null");
    if (order.getItems().isEmpty()) throw new IllegalArgumentException("Order must have items");
    
    // Kalkulacja
    double total = 0;
    for (OrderItem item : order.getItems()) {
        total += item.getPrice() * item.getQuantity();
    }
    
    // Zapis
    database.save(order);
    emailService.sendConfirmation(order.getCustomerEmail());
}

// PO: Podzielone na logiczne części
public void processOrder(Order order) {
    validateOrder(order);
    double total = calculateOrderTotal(order);
    saveOrderAndNotify(order);
}

private void validateOrder(Order order) {
    if (order == null) {
        throw new IllegalArgumentException("Order cannot be null");
    }
    if (order.getItems().isEmpty()) {
        throw new IllegalArgumentException("Order must have items");
    }
}

private double calculateOrderTotal(Order order) {
    return order.getItems().stream()
            .mapToDouble(item -> item.getPrice() * item.getQuantity())
            .sum();
}

private void saveOrderAndNotify(Order order) {
    database.save(order);
    emailService.sendConfirmation(order.getCustomerEmail());
}
Pro tip: Nazwy metod powinny mówić CO robią, nie JAK. Zamiast checkOrderData() użyj validateOrder().

Rename Variable – lepsze nazwy zmiennych

// PRZED: Niejasne nazwy
public double calc(List items) {
    double t = 0;
    for (Item i : items) {
        double p = i.getPrice();
        int q = i.getQuantity();
        t += p * q;
    }
    return t;
}

// PO: Czytelne nazwy
public double calculateTotalPrice(List items) {
    double totalPrice = 0;
    for (Item item : items) {
        double itemPrice = item.getPrice();
        int quantity = item.getQuantity();
        totalPrice += itemPrice * quantity;
    }
    return totalPrice;
}

Bezpieczny refactoring z IDE

Nowoczesne IDE jak IntelliJ IDEA czy Eclipse mają wbudowane narzędzia refactoringu, które minimalizują ryzyko wprowadzenia błędów.

IntelliJ IDEA 2016 – najważniejsze skróty refactoringu:
• Ctrl+Alt+M – Extract Method
• Shift+F6 – Rename
• Ctrl+Alt+V – Extract Variable
• Ctrl+Alt+C – Extract Constant

Krok po kroku: Extract Method w IntelliJ IDEA

1. Zaznacz fragment kodu który chcesz wyciągnąć
2. Naciśnij Ctrl+Alt+M
3. Wpisz nazwę nowej metody
4. IDE automatycznie wykryje parametry i typ zwracany
5. Zatwierdź – IDE zastąpi wszystkie podobne fragmenty

Uwaga: Zawsze uruchom testy po refactoringu! IDE jest mądre, ale nie beźbłędne. Szczególnie uważaj na zmienne o tym samym typie ale różnym znaczeniu.

Kiedy refactorować, a kiedy nie

Refactoruj gdy:

  • Dodajesz nową funkcjonalność – „Rule of Three”: gdy robisz coś po raz trzeci, refactoruj
  • Naprawiasz błąd – często błędy są w brudnym kodzie
  • Kod review – świeże spojrzenie ujawnia zapachy kodu
  • Nie rozumiesz kodu – nawet własnego sprzed miesiąca

NIE refactoruj gdy:

  • Zbliża się deadline – refactoring to inwestycja długoterminowa
  • Kod działa i nie będzie zmieniany – „if it ain’t broken, don’t fix it”
  • Brak testów – refactoring bez testów to hazard
Błąd początkujących: Refactoring „bo można”. Zawsze refactoruj z konkretnym celem – poprawa czytelności, wydajności lub przygotowanie do nowej funkcjonalności.

Testy jako sieć bezpieczeństwa

Przed każdym refactoringiem napisz testy jednostkowe. To Twoja polisa ubezpieczeniowa – jeśli coś zepsujesz, od razu się dowiesz.

@Test
public void shouldCalculateOrderTotalCorrectly() {
    // Given
    Order order = new Order();
    order.addItem(new OrderItem("Book", 29.99, 2));
    order.addItem(new OrderItem("Pen", 1.50, 3));
    
    // When
    double total = orderService.calculateOrderTotal(order);
    
    // Then
    assertEquals(64.48, total, 0.01);
}
Refactoring bez testów to jak remont domu bez sprawdzenia czy fundament jest stabilny. Możesz zrobić piękne wnętrze, ale jeśli zawalą się ściany, cała praca pójdzie na marne.
Jak często powinienem refactorować kod?

Refactoring powinien być częścią codziennej pracy, nie osobnym zadaniem. Zasada „Boy Scout Rule”: zostaw kod w lepszym stanie niż go zastałeś. Nawet 5-10 minut refactoringu dziennie przynosi ogromne korzyści długoterminowe.

Czy mogę refactorować kod którego nie pisałem?

Tak, ale bądź ostrożny. Najpierw zrozum biznesową logikę kodu, napisz testy, a potem refactoruj małymi krokami. Skonsultuj się z autorem kodu lub tech leadem jeśli masz wątpliwości.

Co zrobić jeśli manager mówi że refactoring to strata czasu?

Przedstaw argumenty biznesowe: refactoring skraca czas rozwoju nowych funkcji, redukuje liczbę błędów i ułatwia wdrażanie nowych programistów. Zaproponuj „mikro-refactoring” – małe poprawki przy okazji innych zadań.

Które narzędzia refactoringu w IDE są najważniejsze?

Zacznij od Extract Method (Ctrl+Alt+M), Rename (Shift+F6) i Extract Constant (Ctrl+Alt+C). Te trzy pokrywają 80% potrzeb refactoringu. Później poznaj Move Method i Change Method Signature.

Jak przekonać zespół do refactoringu?

Zacznij od własnego kodu, pokaż konkretne przykłady poprawy. Wprowadź „Definition of Done” która zawiera minimalny poziom czystości kodu. Organizuj code review skupione na jakości, nie tylko funkcjonalności.

Co to jest „refactoring debt”?

To skumulowane problemy w kodzie które utrudniają rozwój. Jak dług finansowy – im dłużej odkładasz spłatę, tym wyższe odsetki. Regularne małe refactoring zapobiega „bankructwu technicznemu” projektu.

Czy refactoring może wprowadzić nowe błędy?

Tak, dlatego kluczowe są testy automatyczne i małe kroki. Refactoruj po jednej zmianie na raz, uruchamiaj testy po każdej zmianie. Używaj narzędzi IDE zamiast ręcznych zmian – to minimalizuje ryzyko.

Przydatne zasoby

🚀 Zadanie dla Ciebie

Refactoring Challenge: Znajdź w swoim projekcie metodę dłuższą niż 20 linijek. Zastosuj Extract Method żeby podzielić ją na 3-4 mniejsze metody z opisowymi nazwami. Przed refactoringiem napisz test jednostkowy, po refactoringu sprawdź czy test dalej przechodzi.

Bonus: Znajdź w kodzie 3 magiczne liczby i zamień je na named constants. Udostępnij rezultat w komentarzu – czy kod stał się bardziej czytelny?

Czy masz swoje ulubione techniki refactoringu? Może zmagałeś się z szczególnie trudnym „zapachem kodu”? Podziel się swoimi doświadczeniami w komentarzach!

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Przewijanie do góry