Code Smell Detector
Overview
Identify code quality and design smells in Python codebases, then provide specific refactoring recommendations to improve maintainability and design.
Workflow
1. Understand the Analysis Scope
Define what to analyze:
Questions to ask:
- What directory or files should be analyzed?
- Focus on quality smells, design smells, or both?
- Are there specific concerns (e.g., "this class is too complex")?
- Should test files be included?
Determine scope:
# Check project structure
ls -la
# Count Python files
find . -name "*.py" | wc -l
# Identify large files (potential smells)
find . -name "*.py" -exec wc -l {} + | sort -rn | head -10
2. Detect Code Smells
Use multiple detection strategies.
Strategy 1: Automated Detection
Use the bundled script for AST-based analysis:
# Scan entire project
python scripts/detect_smells.py /path/to/project
# Exclude specific directories
python scripts/detect_smells.py /path/to/project venv,tests,docs
What it detects:
- Long methods (>50 lines)
- Too many parameters (>5)
- Large classes (>15 methods)
- God classes (>20 methods)
- Magic numbers
Strategy 2: Manual Code Review
Read the code to identify design smells. See smell-patterns.md for comprehensive catalog.
Look for:
Code Quality Smells:
- Duplicate code blocks
- Magic numbers (unexplained numeric literals)
- Hardcoded values (paths, URLs, config)
- Commented-out code
- Inconsistent naming
Design Smells:
- God classes (too many responsibilities)
- Feature envy (method uses more from another class)
- Inappropriate intimacy (classes too coupled)
- Data clumps (same parameters repeated)
- Primitive obsession (using primitives instead of objects)
- Long parameter lists (>5 parameters)
Search patterns:
# Find long files (potential large classes)
find . -name "*.py" -exec wc -l {} + | awk '$1 > 300'
# Find magic numbers (basic pattern)
grep -r "[^0-9]\d\{3,\}" --include="*.py" .
# Find hardcoded paths
grep -r '"/.*/"' --include="*.py" .
# Find commented code
grep -r "^[ ]*#.*def \|^[ ]*#.*class " --include="*.py" .
Strategy 3: Use External Tools
radon - Complexity metrics:
# Install
pip install radon
# Check cyclomatic complexity
radon cc /path/to/project -a
# Maintainability index
radon mi /path/to/project
# Show only complex functions
radon cc /path/to/project -nc
pylint - Code quality:
pip install pylint
# Check for code smells
pylint /path/to/project --disable=C0111 # Disable docstring warnings
3. Categorize Smells
Organize findings by severity and type.
See smell-patterns.md for detailed patterns.
High Severity
Immediate attention needed:
- God classes (>20 methods, multiple responsibilities)
- Shotgun surgery (changes ripple across many files)
- Feature envy (method belongs in different class)
- Long parameter lists (>7 parameters)
Medium Severity
Should refactor soon:
- Large classes (>15 methods)
- Duplicate code
- Data clumps
- Primitive obsession
- Inappropriate intimacy
Low Severity
Nice to improve:
- Magic numbers
- Hardcoded values
- Inconsistent naming
- Lazy classes
- Commented-out code
4. Identify Refactorings
For each smell, determine appropriate refactoring.
See refactoring-patterns.md for detailed examples.
Common mappings:
| Smell | Refactoring |
|---|---|
| God class | Extract Class, Extract Service |
| Feature envy | Move Method |
| Duplicate code | Extract Method, Pull Up Method |
| Data clumps | Introduce Parameter Object |
| Magic numbers | Replace with Symbolic Constant |
| Long parameter list | Introduce Parameter Object |
| Primitive obsession | Replace Data Value with Object |
| Inappropriate intimacy | Move Method, Hide Delegate |
| Shotgun surgery | Move Method, Inline Class |
| Lazy class | Inline Class, Collapse Hierarchy |
5. Generate Report
Create a structured markdown report with specific refactoring recommendations.
Code Smell Analysis Report
Project: [Project Name] Analyzed: [Date] Scope: [Directories analyzed] Excluded: [Excluded directories]
Summary
- High severity smells: X issues
- Medium severity smells: Y issues
- Low severity smells: Z issues
Total: N code smells detected
🔴 High Severity Smells
Smell 1: God Class
Location: src/services/user_manager.py:15
Class: UserManager
Description: Class has 28 methods handling multiple unrelated responsibilities (user CRUD, authentication, email, logging, analytics).
Impact:
- Violates Single Responsibility Principle
- Hard to test and maintain
- Changes ripple across unrelated features
Refactoring: Extract Class
Recommendation:
Split into focused classes by responsibility:
# Before: God class with 28 methods
class UserManager:
def create_user(self, data): pass
def update_user(self, user_id, data): pass
def delete_user(self, user_id): pass
def authenticate(self, username, password): pass
def hash_password(self, password): pass
def send_welcome_email(self, user): pass
def send_password_reset(self, user): pass
def log_activity(self, user, action): pass
def get_statistics(self, user): pass
# ... 19 more methods
# After: Split by responsibility
class UserRepository:
"""Handles user persistence."""
def create(self, data): pass
def update(self, user_id, data): pass
def delete(self, user_id): pass
def find_by_id(self, user_id): pass
class UserAuthService:
"""Handles authentication."""
def authenticate(self, username, password): pass
def hash_password(self, password): pass
def validate_password_strength(self, password): pass
class UserNotificationService:
"""Handles user notifications."""
def send_welcome_email(self, user): pass
def send_password_reset(self, user): pass
class UserAnalyticsService:
"""Handles user analytics."""
def log_activity(self, user, action): pass
def get_statistics(self, user): pass
Priority: High - Refactor within 1-2 sprints
Smell 2: Feature Envy
Location: src/models/order.py:45
Method: Order.calculate_total()
Description: Method uses customer features heavily (discount_rate, is_premium, shipping_address) rather than its own class features.
Impact:
- Poor cohesion - method is in wrong class
- Changes to Customer affect Order
- Violates "tell, don't ask" principle
Refactoring: Move Method
Recommendation:
Move calculation logic to Customer class:
# Before: Feature envy
class Order:
def calculate_total(self):
discount = self.customer.get_discount_rate()
is_premium = self.customer.is_premium_member()
address = self.customer.get_shipping_address()
total = sum(item.price for item in self.items)
if is_premium:
total *= (1 - discount)
if address.country != 'US':
total += 50
return total
# After: Move to appropriate class
class Customer:
def calculate_order_total(self, items):
total = sum(item.price for item in items)
if self.is_premium_member():
total *= (1 - self.get_discount_rate())
if self.shipping_address.country != 'US':
total += 50
return total
class Order:
def calculate_total(self):
return self.customer.calculate_order_total(self.items)
Priority: High - Refactor within 2 weeks
🟡 Medium Severity Smells
Smell 3: Duplicate Code
Locations:
src/validators/user_validator.py:23-35src/validators/profile_validator.py:45-57
Description: Identical email and name validation logic appears in two validators.
Impact:
- Changes must be made in multiple places
- Risk