refactoring-assistant
Skill0 starsChanged 13 months agoMITView on GitHub
Code refactoring assistant for identifying code smells, suggesting design patterns, and improving code quality
- Installs packages
1 other project uses a version of this.
Adopted by
Most recently taken up by
- mehdiozdemir/awesome-agent-skillstheir own version, first seen Jan 16, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- mehdiozdemir/awesome-agent-skills★ 2same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository16 other files it gives its agents.
- aws-cost-analyzerSkill
- code-reviewerSkill
- dast-scannerSkill
- database-optimizerSkill
- dependency-checkerSkill
- git-workflowSkill
- java-profilerSkill
- jira-integrationSkill
- memory-analyzerSkill
- penetration-testerSkill
- performance-monitorSkill
- python-profilerSkill
- sast-analyzerSkill
- security-scannerSkill
- skill-validatorSkill
- tdd-workflowSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 4 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 40
Add tests before refactoring
- Distinctive: line 41
Ensure tests pass after each step
- Distinctive: line 619
Test First: Always have tests before refactoring
- Distinctive: line 621
Continuous Testing: Run tests after each change
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Refactoring Assistant Skill
Overview
Systematic refactoring skill for identifying code smells, applying design patterns, improving maintainability, and transforming legacy code into clean, testable architecture.
Capabilities
1. Code Smell Detection
- Long methods
- Large classes
- Duplicate code
- Dead code
- Complex conditionals
- Primitive obsession
- Feature envy
- Data clumps
2. Refactoring Patterns
- Extract Method/Function
- Extract Class
- Introduce Parameter Object
- Replace Conditional with Polymorphism
- Replace Magic Numbers with Constants
- Consolidate Duplicate Conditional Fragments
3. Design Pattern Application
- Strategy Pattern
- Factory Pattern
- Observer Pattern
- Decorator Pattern
- Dependency Injection
- Repository Pattern
4. Testing Support
- Add tests before refactoring
- Ensure tests pass after each step
- Improve test coverage during refactoring
Common Code Smells & Solutions
1. Long Method
Smell: Method with too many lines (>50)
Before:
def process_order(order_data):
# Validate (20 lines)
if not order_data.get('email'):
return {'error': 'Email required'}
if not order_data.get('items'):
return {'error': 'Items required'}
# ... more validation
# Calculate totals (30 lines)
subtotal = 0
for item in order_data['items']:
price = get_price(item['id'])
quantity = item['quantity']
subtotal += price * quantity
# ... more calculation
# Save to database (15 lines)
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute("INSERT INTO orders ...")
# ... more database code
# Send email (20 lines)
smtp = smtplib.SMTP('smtp.gmail.com')
# ... email code
return {'success': True}Refactoring: Extract Method
def process_order(order_data):
validation_errors = validate_order(order_data)
if validation_errors:
return {'errors': validation_errors}, 400
order_total = calculate_order_total(order_data)
order_id = save_order(order_data, order_total)
send_order_confirmation(order_data['email'], order_id)
return {'order_id': order_id}, 201
def validate_order(order_data):
errors = []
if not order_data.get('email'):
errors.append('Email required')
if not order_data.get('items'):
errors.append('Items required')
return errors
def calculate_order_total(order_data):
return sum(
get_price(item['id']) * item['quantity']
for item in order_data['items']
)
def save_order(order_data, total):
# Database logic
pass
def send_order_confirmation(email, order_id):
# Email logic
pass2. Large Class (God Object)
Smell: Class with too many responsibilities
Before:
class UserManager {
public void createUser(String email, String password) { }
public void deleteUser(int id) { }
public void updateUser(int id, User data) { }
public User findUser(int id) { }
public void sendEmail(String to, String subject) { }
public void sendSMS(String phone, String message) { }
public void logActivity(String activity) { }
public void logError(String error) { }
public void generateReport() { }
public void exportToCsv() { }
// 50+ methods...
}Refactoring: Extract Class
// Separate concerns
class UserRepository {
public void create(User user) { }
public void delete(int id) { }
public void update(int id, User data) { }
public User findById(int id) { }
}
class NotificationService {
public void sendEmail(String to, String subject, String body) { }
public void sendSMS(String phone, String message) { }
}
class Logger {
public void logActivity(String activity) { }
public void logError(String error) { }
}
class ReportGenerator {
public void generateReport() { }
public void exportToCsv() { }
}
class UserService {
private UserRepository repository;
private NotificationService notifications;
private Logger logger;
public void createUser(String email, String password) {
User user = new User(email, password);
repository.create(user);
notifications.sendEmail(email, "Welcome!");
logger.logActivity("User created: " + email);
}
}3. Duplicate Code
Smell: Same code in multiple places
Before:
function calculateTotalPrice(items) {
let total = 0;
for (let item of items) {
total += item.price * item.quantity;
}
total = total * 1.1; // 10% tax
return total;
}
function calculateCartPrice(cart) {
let total = 0;
for (let item of cart.items) {
total += item.price * item.quantity;
}
total = total * 1.1; // 10% tax
return total;
}
function calculateInvoiceTotal(invoice) {
let total = 0;
for (let line of invoice.lines) {
total += line.price * line.quantity;
}
total = total * 1.1; // 10% tax
return total;
}Refactoring: Eliminate Duplication
function calculateTotal(items) {
const subtotal = items.reduce(
(sum, item) => sum + (item.price * item.quantity),
0
);
return applyTax(subtotal);
}
function applyTax(amount) {
const TAX_RATE = 0.1;
return amount * (1 + TAX_RATE);
}
// Usage
const orderTotal = calculateTotal(order.items);
const cartTotal = calculateTotal(cart.items);
const invoiceTotal = calculateTotal(invoice.lines);4. Complex Conditional
Smell: Nested if-else statements
Before:
def get_shipping_cost(order):
if order.total > 100:
if order.customer.premium:
if order.destination == 'domestic':
return 0
else:
return 10
else:
if order.destination == 'domestic':
return 5
else:
return 20
else:
if order.customer.premium:
if order.destination == 'domestic':
return 3
else:
return 15
else:
if order.destination == 'domestic':
return 8
else:
return 25Refactoring: Strategy Pattern
class ShippingStrategy:
def calculate_cost(self, order):
raise NotImplementedError
class PremiumDomesticShipping(ShippingStrategy):
def calculate_cost(self, order):
return 0 if order.total > 100 else 3
class PremiumInternationalShipping(ShippingStrategy):
def calculate_cost(self, order):
return 10 if order.total > 100 else 15
class StandardDomesticShipping(ShippingStrategy):
def calculate_cost(self, order):
return 5 if order.total > 100 else 8
class StandardInternationalShipping(ShippingStrategy):
def calculate_cost(self, order):
return 20 if order.total > 100 else 25
class ShippingCalculator:
def __init__(self):
self.strategies = {
('premium', 'domestic'): PremiumDomesticShipping(),
('premium', 'international'): PremiumInternationalShipping(),
('standard', 'domestic'): StandardDomesticShipping(),
('standard', 'international'): StandardInternationalShipping(),
}
def calculate(self, order):
customer_type = 'premium' if order.customer.premium else 'standard'
key = (customer_type, order.destination)
strategy = self.strategies[key]
return strategy.calculate_cost(order)5. Primitive Obsession
Smell: Using primitives instead of small objects
Before:
class Order {
private String customerEmail; // Primitives everywhere
private String customerPhone;
private String shippingAddress;
private String billingAddress;
public boolean isValidEmail() {
return customerEmail.matches("^[A-Za-z0-9+_.-]+@(.+)$");
}
public boolean isValidPhone() {
return customerPhone.matches("\\d{10}");
}
}Refactoring: Introduce Value Objects
class Email {
private final String value;
public Email(String value) {
if (!isValid(value)) {
throw new IllegalArgumentException("Invalid email");
}
this.value = value;
}
private boolean isValid(String email) {
return email.matches("^[A-Za-z0-9+_.-]+@(.+)$");
}
public String getValue() { return value; }
}
class PhoneNumber {
private final String value;
public PhoneNumber(String value) {
if (!isValid(value)) {
throw new IllegalArgumentException("Invalid phone");
}
this.value = value;
}
private boolean isValid(String phone) {
return phone.matches("\\d{10}");
}
}
class Address {
private final String street;
private final String city;
private final String zipCode;
// Constructor with validation
}
class Order {
private Email customerEmail;
private PhoneNumber customerPhone;
private Address shippingAddress;
private Address billingAddress;
// No validation needed - value objects ensure validity
}6. Feature Envy
Smell: Method in one class uses data from another class more than its own
Before:
class Order:
def __init__(self, customer):
self.customer = customer
def calculate_discount(self):
# Feature envy - uses customer data extensively
if self.customer.membership_years > 5:
if self.customer.total_purchases > 10000:
return 0.20
elif self.customer.total_purchases > 5000:
return 0.15
else:
return 0.10
elif self.customer.membership_years > 2:
return 0.05
else:
return 0Refactoring: Move Method
class Customer:
def __init__(self, membership_years, total_purchases):
self.membership_years = membership_years
self.total_purchases = total_purchases
def get_discount_rate(self):
if self.membership_years > 5:
if self.total_purchases > 10000:
return 0.20
elif self.total_purchases > 5000:
return 0.15
else:
return 0.10
elif self.membership_years > 2:
return 0.05
else:
return 0
class Order:
def __init__(self, customer):
self.customer = customer
def calculate_discount(self):
return self.customer.get_discount_rate()Refactoring Workflow
Safe Refactoring Process
- Write Tests First
# Ensure existing tests pass
pytest tests/
# Add tests if coverage is low
pytest --cov=src tests/- Make Small Changes
# Don't refactor everything at once
# Refactor one method/class at a time- Run Tests After Each Change
# After each refactoring step
pytest tests/- Commit Frequently
git add .
git commit -m "refactor: extract calculate_total method"- Review Changes
git diff HEAD~1Integration Scripts
refactor_detector.py
Detect code smells:
#!/usr/bin/env python3
import ast
import os
class RefactoringDetector(ast.NodeVisitor):
def __init__(self):
self.long_methods = []
self.complex_methods = []
self.large_classes = []
def visit_FunctionDef(self, node):
# Long method detection
lines = node.end_lineno - node.lineno
if lines > 50:
self.long_methods.append({
'name': node.name,
'lines': lines,
'line_start': node.lineno
})
# Complexity detection (rough estimate)
complexity = self.calculate_complexity(node)
if complexity > 10:
self.complex_methods.append({
'name': node.name,
'complexity': complexity,
'line': node.lineno
})
self.generic_visit(node)
def visit_ClassDef(self, node):
# Large class detection
methods = [n for n in node.body if isinstance(n, ast.FunctionDef)]
if len(methods) > 20:
self.large_classes.append({
'name': node.name,
'methods': len(methods),
'line': node.lineno
})
self.generic_visit(node)
def calculate_complexity(self, node):
complexity = 1
for child in ast.walk(node):
if isinstance(child, (ast.If, ast.While, ast.For, ast.ExceptHandler)):
complexity += 1
return complexity
def analyze_file(filepath):
with open(filepath) as f:
tree = ast.parse(f.read(), filepath)
detector = RefactoringDetector()
detector.visit(tree)
return detector
def scan_directory(directory):
print("=== Refactoring Opportunities ===\n")
all_long_methods = []
all_complex_methods = []
all_large_classes = []
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith('.py'):
filepath = os.path.join(root, file)
try:
detector = analyze_file(filepath)
if detector.long_methods:
for method in detector.long_methods:
method['file'] = filepath
all_long_methods.append(method)
if detector.complex_methods:
for method in detector.complex_methods:
method['file'] = filepath
all_complex_methods.append(method)
if detector.large_classes:
for cls in detector.large_classes:
cls['file'] = filepath
all_large_classes.append(cls)
except:
pass
# Report findings
if all_long_methods:
print(f"⚠️ Long Methods ({len(all_long_methods)}):")
for method in all_long_methods[:10]:
print(f" {method['file']}:{method['line_start']}")
print(f" {method['name']}: {method['lines']} lines")
print(f" 💡 Consider extracting into smaller methods\n")
if all_complex_methods:
print(f"\n⚠️ Complex Methods ({len(all_complex_methods)}):")
for method in all_complex_methods[:10]:
print(f" {method['file']}:{method['line']}")
print(f" {method['name']}: complexity = {method['complexity']}")
print(f" 💡 Consider simplifying or extracting logic\n")
if all_large_classes:
print(f"\n⚠️ Large Classes ({len(all_large_classes)}):")
for cls in all_large_classes[:10]:
print(f" {cls['file']}:{cls['line']}")
print(f" {cls['name']}: {cls['methods']} methods")
print(f" 💡 Consider splitting into smaller classes\n")
if __name__ == '__main__':
import sys
directory = sys.argv[1] if len(sys.argv) > 1 else '.'
scan_directory(directory)duplicate_detector.sh
Find duplicate code:
#!/bin/bash
# Detect duplicate code blocks
PROJECT_DIR=${1:-.}
echo "=== Duplicate Code Detection ==="
# Python
if command -v pylint &> /dev/null; then
echo "Checking Python files..."
pylint --disable=all --enable=duplicate-code $PROJECT_DIR
fi
# JavaScript
if command -v jscpd &> /dev/null; then
echo "Checking JavaScript files..."
jscpd $PROJECT_DIR --min-lines 5 --min-tokens 50
fi
# Java
if command -v cpd &> /dev/null; then
echo "Checking Java files..."
cpd --minimum-tokens 50 --files $PROJECT_DIR --language java
fiBest Practices
- Test First: Always have tests before refactoring
- Small Steps: One refactoring at a time
- Continuous Testing: Run tests after each change
- Commit Often: Version control each successful step
- Don't Change Behavior: Refactoring shouldn't add features
- Use IDE Tools: Automated refactoring when possible
- Code Reviews: Get feedback on refactored code
- Measure Impact: Track complexity, duplication metrics
Common Refactoring Patterns
| Code Smell | Refactoring Solution |
| Long Method | Extract Method |
| Large Class | Extract Class |
| Duplicate Code | Extract Method/Function |
| Long Parameter List | Introduce Parameter Object |
| Primitive Obsession | Replace with Value Object |
| Switch Statements | Replace with Polymorphism |
| Temporary Field | Extract Class |
| Feature Envy | Move Method |
| Data Clumps | Extract Class |
| Magic Numbers | Replace with Named Constants |
Requirements
# Python
pip install pylint radon
# JavaScript
npm install -g jscpd
# Java
# PMD (includes CPD)
wget https://github.com/pmd/pmd/releases/download/pmd_releases%2F6.55.0/pmd-bin-6.55.0.zipMetrics to Track
- Code complexity: Trending down
- Method length: < 50 lines
- Class size: < 20 methods
- Code duplication: < 5%
- Test coverage: Maintained or improved
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

