Skip to main content

refactoring-techniques

Catalog of refactoring techniques from refactoring.guru - how to apply Extract Method, Move Field, Replace Conditional, and 60+ other refactorings

Informations de source

Dépôt
ROCm/rocprofiler-systems-skills
Dernière activité de la source
16 mars 2026 à 11:36
Langue détectée de SKILL.md
anglais
Étoiles
4
Forks
0

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
name
refactoring-techniques
description
Catalog of refactoring techniques from refactoring.guru - how to apply Extract Method, Move Field, Replace Conditional, and 60+ other refactorings
# Refactoring Techniques Catalog Comprehensive reference of refactoring techniques for transforming code while preserving behavior. Based on [Refactoring.Guru Techniques](https://refactoring.guru/refactoring/techniques). <IMPORTANT> This skill is a **reference catalog** for applying refactorings. It is used by: - `planning-refactor` when implementing improvements - `code-smells` to suggest fixes for detected smells - Standalone refactoring assistance **Cross-Reference:** See `code-smells` skill for detecting WHAT to fix. This skill shows HOW to fix it. </IMPORTANT> ## When to Use | Context | Trigger | |---------|---------| | **Planning Refactor** | Need specific technique to fix identified smell | | **Code Review** | Suggesting improvements during PR review | | **Learning** | User asks how to apply a specific refactoring | | **Quick Fix** | User wants to apply a refactoring immediately | ## Quick Reference: Smell to Refactoring | Code Smell | Recommended Refactorings | |------------|-------------------------| | Long Method | Extract Method, Replace Temp with Query, Decompose Conditional | | Large Class | Extract Class, Extract Subclass, Extract Interface | | Long Parameter List | Introduce Parameter Object, Preserve Whole Object | | Duplicate Code | Extract Method, Pull Up Method, Form Template Method | | Feature Envy | Move Method, Extract Method | | Switch Statements | Replace Conditional with Polymorphism, Replace Type Code with Subclasses | | Data Clumps | Extract Class, Introduce Parameter Object | | Primitive Obsession | Replace Data Value with Object, Replace Type Code with Class | | Shotgun Surgery | Move Method, Move Field, Inline Class | | Divergent Change | Extract Class | | Message Chains | Hide Delegate | | Middle Man | Remove Middle Man | | Refused Bequest | Replace Inheritance with Delegation | --- ## Category 1: Composing Methods Techniques for correctly structuring methods. Long methods are often the root of many problems. ### Extract Method | Aspect | Details | |--------|---------| | **Impact** | High - Most frequently used refactoring | | **Risk** | Low | | **Fixes** | Long Method, Duplicate Code, Comments | **Problem:** Code fragment that can be logically grouped together. **Solution:** Create a new method with a descriptive name and move the fragment there. **Steps:** 1. Create new method named after WHAT it does (not HOW) 2. Copy the code fragment to the new method 3. Look for local variables used only within the fragment - make them local to new method 4. Pass external variables as parameters 5. If extracted code modifies a variable needed later, return it 6. Replace original fragment with method call **C++ Example:** ```cpp // BEFORE void print_invoice(const Invoice& inv) { // Print header std::cout << "================\n"; std::cout << "INVOICE #" << inv.number << "\n"; std::cout << "Date: " << inv.date << "\n"; std::cout << "================\n"; // Print items for (const auto& item : inv.items) { std::cout << item.name << ": $" << item.price << "\n"; } // Calculate and print total double total = 0; for (const auto& item : inv.items) { total += item.price; } std::cout << "Total: $" << total << "\n"; } // AFTER void print_header(const Invoice& inv) { std::cout << "================\n"; std::cout << "INVOICE #" << inv.number << "\n"; std::cout << "Date: " << inv.date << "\n"; std::cout << "================\n"; } void print_items(const std::vector<Item>& items) { for (const auto& item : items) { std::cout << item.name << ": $" << item.price << "\n"; } } double calculate_total(const std::vector<Item>& items) { return std::accumulate(items.begin(), items.end(), 0.0, [](double sum, const Item& item) { return sum + item.price; }); } void print_invoice(const Invoice& inv) { print_header(inv); print_items(inv.items); std::cout << "Total: $" << calculate_total(inv.items) << "\n"; } ``` **Python Example:** ```python # BEFORE def print_invoice(inv): # Print header print("================") print(f"INVOICE #{inv.number}") print(f"Date: {inv.date}") print("================") # Print items and calculate total total = 0 for item in inv.items: print(f"{item.name}: ${item.price}") total += item.price print(f"Total: ${total}") # AFTER def print_header(inv): print("================") print(f"INVOICE #{inv.number}") print(f"Date: {inv.date}") print("================") def print_items(items): for item in items: print(f"{item.name}: ${item.price}") def calculate_total(items): return sum(item.price for item in items) def print_invoice(inv): print_header(inv) print_items(inv.items) print(f"Total: ${calculate_total(inv.items)}") ``` --- ### Inline Method | Aspect | Details | |--------|---------| | **Impact** | Low | | **Risk** | Low | | **Fixes** | Speculative Generality, excessive delegation | **Problem:** Method body is more obvious than the method itself. **Solution:** Replace method calls with the method content and delete the method. **Steps:** 1. Verify method is not overridden in subclasses 2. Find all calls to the method 3. Replace each call with the method body 4. Delete the method ```cpp // BEFORE int get_rating() { return more_than_five_late_deliveries() ? 2 : 1; } bool more_than_five_late_deliveries() { return late_deliveries_ > 5; } // AFTER int get_rating() { return late_deliveries_ > 5 ? 2 : 1; } ``` --- ### Extract Variable | Aspect | Details | |--------|---------| | **Impact** | Medium | | **Risk** | Low | | **Fixes** | Complex expressions, Comments | **Problem:** Hard-to-understand expression. **Solution:** Place the expression result in a self-explanatory variable. **Steps:** 1. Insert a new variable and assign the expression to it 2. Replace the original expression with the variable 3. Repeat for other occurrences of the same expression ```cpp // BEFORE if (platform.find("MAC") != std::string::npos && browser.find("IE") != std::string::npos && was_initialized() && resize > 0) { // ... } // AFTER bool is_mac = platform.find("MAC") != std::string::npos; bool is_ie = browser.find("IE") != std::string::npos; bool was_resized = resize > 0; if (is_mac && is_ie && was_initialized() && was_resized) { // ... } ``` --- ### Replace Temp with Query | Aspect | Details | |--------|---------| | **Impact** | Medium | | **Risk** | Low | | **Fixes** | Long Method (preparation for Extract Method) | **Problem:** Temporary variable storing an expression result for later use. **Solution:** Move the expression to a new method and call the method instead of using the variable. **Steps:** 1. Ensure the variable is only assigned once 2. Extract the expression into a new method 3. Replace all uses of the variable with method calls 4. Remove the variable declaration ```cpp // BEFORE double calculate_total() { double base_price = quantity_ * item_price_; if (base_price > 1000) { return base_price * 0.95; } return base_price * 0.98; } // AFTER double base_price() const { return quantity_ * item_price_; } double calculate_total() { if (base_price() > 1000) { return base_price() * 0.95; } return base_price() * 0.98; } ``` --- ### Split Temporary Variable | Aspect | Details | |--------|---------| | **Impact** | Medium | | **Risk** | Low | | **Fixes** | Variable reuse, unclear intent | **Problem:** Local variable used for multiple unrelated purposes. **Solution:** Create separate variables for each purpose. ```cpp // BEFORE double temp = 2 * (height_ + width_); std::cout << "Perimeter: " << temp << "\n"; temp = height_ * width_; std::cout << "Area: " << temp << "\n"; // AFTER double perimeter = 2 * (height_ + width_); std::cout << "Perimeter: " << perimeter << "\n"; double area = height_ * width_; std::cout << "Area: " << area << "\n"; ``` --- ### Remove Assignments to Parameters | Aspect | Details | |--------|---------| | **Impact** | Medium | | **Risk** | Low | | **Fixes** | Confusing parameter modification | **Problem:** Value assigned to a parameter inside method body. **Solution:** Use a local variable instead of the parameter. ```cpp // BEFORE int discount(int input_val, int quantity) { if (quantity > 50) { input_val -= 2; // Modifying parameter! } return input_val; } // AFTER int discount(int input_val, int quantity) { int result = input_val; if (quantity > 50) { result -= 2; } return result; } ``` --- ### Replace Method with Method Object | Aspect | Details | |--------|---------| | **Impact** | High | | **Risk** | Medium | | **Fixes** | Long Method with intertwined local variables | **Problem:** Long method where local variables prevent extraction. **Solution:** Transform the method into a separate class where locals become fields. **Steps:** 1. Create a new class named after the method 2. Create a private field for the original object and each local variable/parameter 3. Create a constructor that initializes all fields 4. Copy the method body to a `compute()` method in the new class 5. Replace original method with creation of method object and call to `compute()` ```cpp // BEFORE class Order {
Voir sur GitHub
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section. Voir sur GitHub