C++:
Рефакторинг

Як це зробити:

Уявіть, що у вас є функція, яка робить трохи забагато, як от цей складний метод, що ініціалізує об’єкт, а також виконує логування:

#include <iostream>

class Widget {
public:
    void init(bool verbose) {
        // Логіка ініціалізації
        // ...

        // Детальне логування
        if (verbose) {
            std::cout << "Віджет ініціалізовано!" << std::endl;
        }
    }
};

// Використання:
Widget w;
w.init(true);

Вивід:

Віджет ініціалізовано!

Рефакторинг цього до чистіших, більш фокусованих методів може виглядати так:

#include <iostream>

class Widget {
public:
    void init() {
        // Тільки логіка ініціалізації
        // ...
    }

    void logInitialization() const {
        std::cout << "Віджет ініціалізовано!" << std::endl;
    }
};

// Використання:
Widget w;
w.init();
w.logInitialization();

Ця зміна не змінила те, що робить програма, але зробила клас Widget більш модульним і його використання більш зрозумілим.

Поглиблений огляд

Концепція рефакторингу, як ми її знаємо сьогодні, має свої корені у спільнотах програмування на Smalltalk 1980-х років і була сильно популяризована книгою Мартіна Фаулера “Refactoring: Improving the Design of Existing Code” 1999 року. Сьогодні, рефакторинг є основною частиною сучасної розробки програмного забезпечення, інтегрованою в різні методології розробки, такі як Agile та TDD (розробка через тестування).

Коли ми говоримо про альтернативи рефакторингу, ми заходимо в область переписування або перепроектування. Рефакторинг є стратегічним та інкрементним, тоді як переписування може відмовитися від існуючого коду на користь нового рішення. Перепроектування, в свою чергу, може включати значні зміни, включаючи зміну функціональності, що є неціллю для чистого рефакторингу.

Деталі імплементації рефакторингу можуть бути досить детальними. Існує багато “поганих запахів” коду, які можуть спонукати до рефакторингу, такі як довгі методи, великі класи, або дубльований код. Існують автоматизовані інструменти, які можуть допомогти в рефакторингу, такі як “Clang-Tidy” для C++, які можуть виявляти проблеми та навіть застосувати деякі виправлення.

Більше того, для рефакторингу потрібен міцний набір тестів, щоб переконатися, що функціональність залишається незмінною. Без тестів ви по суті літаете всліпу та ризикуєте регресією.

Див. також

Для глибшого розуміння рефакторингу та для більшої кількості прикладів, ви можете ознайомитися з:

  • Класичним текстом Мартіна Фаулера “Refactoring: Improving the Design of Existing Code” для основних ідей та стратегій.
  • Документацією Clang-Tidy за адресою https://clang.llvm.org/extra/clang-tidy/ для автоматизованої підтримки рефакторингу в C++.
  • “Working Effectively with Legacy Code” Майкла Фезерса, який надає техніки безпечного рефакторингу в контексті неідеальних існуючих кодових баз.