232 lines
5.8 KiB
Markdown
232 lines
5.8 KiB
Markdown
# Code Smell Logger Hook
|
|
|
|
This hook analyzes Ruby files after they're written and logs detected code smells to help track refactoring opportunities.
|
|
|
|
## Trigger
|
|
|
|
- Event: post-write
|
|
- Pattern: **/*.rb
|
|
|
|
## Purpose
|
|
|
|
Maintain a running log of code smells to:
|
|
- Track refactoring debt over time
|
|
- Prioritize refactoring efforts
|
|
- Learn from recurring patterns
|
|
- Monitor code quality trends
|
|
|
|
## Analysis Process
|
|
|
|
### 1. Detect Code Smells
|
|
|
|
Analyze the file for common smells based on Sandi Metz's principles:
|
|
|
|
**Complexity Smells:**
|
|
- Methods longer than 5 lines
|
|
- Classes longer than 100 lines
|
|
- Cyclomatic complexity > 3
|
|
- Nested conditionals (depth > 2)
|
|
- Long parameter lists (> 4 parameters)
|
|
|
|
**Design Smells:**
|
|
- Missing dependency injection
|
|
- Feature envy (accessing other objects' data)
|
|
- Data clumps (same parameters used together)
|
|
- Primitive obsession
|
|
- Law of Demeter violations (chained method calls)
|
|
|
|
**OO Design Smells:**
|
|
- Missing single responsibility
|
|
- Unclear public/private interface
|
|
- Deep inheritance (> 1 level)
|
|
- Missing abstraction opportunities
|
|
- Duplication (similar code patterns)
|
|
|
|
**Ruby-Specific Smells:**
|
|
- Missing frozen_string_literal
|
|
- Not using Ruby iterators (using for loops)
|
|
- Not using blocks/yield appropriately
|
|
- Missing null object pattern where appropriate
|
|
- Overly complex conditionals vs polymorphism
|
|
|
|
### 2. Calculate Severity
|
|
|
|
**High Priority:**
|
|
- Multiple responsibilities in one class
|
|
- Deep nesting (> 2 levels)
|
|
- Methods > 10 lines
|
|
- Clear SOLID violations
|
|
|
|
**Medium Priority:**
|
|
- Methods 6-10 lines
|
|
- Missing dependency injection
|
|
- Law of Demeter violations
|
|
- Primitive obsession
|
|
|
|
**Low Priority:**
|
|
- Methods exactly 5 lines
|
|
- Minor style issues
|
|
- Potential improvements (not violations)
|
|
|
|
### 3. Log Format
|
|
|
|
Append to `.claude/code-smells.log`:
|
|
|
|
```
|
|
[TIMESTAMP] - [FILE_PATH]
|
|
Severity: [HIGH/MEDIUM/LOW]
|
|
Smell: [SMELL_NAME]
|
|
Location: [CLASS_NAME]#[METHOD_NAME] (lines X-Y)
|
|
Description: [Specific issue detected]
|
|
Suggestion: [Refactoring approach]
|
|
Related Pattern: [POODR principle or pattern]
|
|
---
|
|
```
|
|
|
|
## Example Output
|
|
|
|
```
|
|
2025-11-01 14:23:15 - lib/user_service.rb
|
|
Severity: HIGH
|
|
Smell: God Object / Multiple Responsibilities
|
|
Location: UserService (lines 1-156)
|
|
Description: Class has 8 public methods handling authentication, validation, email sending, and database operations
|
|
Suggestion: Extract into separate services: UserAuthenticator, UserValidator, UserMailer, UserRepository
|
|
Related Pattern: Single Responsibility Principle (POODR Ch. 2)
|
|
---
|
|
|
|
2025-11-01 14:23:15 - lib/user_service.rb
|
|
Severity: MEDIUM
|
|
Smell: Long Method
|
|
Location: UserService#create_user (lines 23-42)
|
|
Description: Method is 19 lines, handles validation, creation, and email sending
|
|
Suggestion: Extract methods: validate_user_data, persist_user, send_welcome_email
|
|
Related Pattern: Small Methods (Sandi's Rules)
|
|
---
|
|
|
|
2025-11-01 14:23:15 - lib/order_processor.rb
|
|
Severity: MEDIUM
|
|
Smell: Missing Dependency Injection
|
|
Location: OrderProcessor#process (line 15)
|
|
Description: Hard-coded instantiation of EmailMailer.new inside method
|
|
Suggestion: Inject mailer dependency through constructor
|
|
Related Pattern: Dependency Injection (POODR Ch. 3)
|
|
---
|
|
|
|
2025-11-01 14:23:15 - lib/payment_handler.rb
|
|
Severity: LOW
|
|
Smell: Primitive Obsession
|
|
Location: PaymentHandler#validate_card (lines 8-12)
|
|
Description: Using string for credit card number validation
|
|
Suggestion: Create CreditCard value object with validation
|
|
Related Pattern: Value Object pattern
|
|
---
|
|
```
|
|
|
|
## Response to User
|
|
|
|
After logging, provide a brief summary:
|
|
|
|
**Code Smell Analysis Complete**
|
|
|
|
Analyzed: [file_path]
|
|
|
|
**Detected Issues:**
|
|
- 1 High Priority: God Object in UserService
|
|
- 2 Medium Priority: Long method, missing DI
|
|
- 1 Low Priority: Primitive obsession
|
|
|
|
**Top Recommendation:**
|
|
Extract UserService into separate concerns following Single Responsibility Principle.
|
|
|
|
Full details logged to `.claude/code-smells.log`
|
|
|
|
**Quick Actions:**
|
|
- Run `/refactor` to get detailed refactoring plan
|
|
- Run `/review-ruby` for comprehensive code review
|
|
- View log: `cat .claude/code-smells.log | tail -20`
|
|
|
|
## Log Management
|
|
|
|
### View Recent Smells
|
|
```bash
|
|
# Last 20 entries
|
|
tail -20 .claude/code-smells.log
|
|
|
|
# Smells from specific file
|
|
grep "lib/user.rb" .claude/code-smells.log
|
|
|
|
# High priority only
|
|
grep "Severity: HIGH" .claude/code-smells.log
|
|
|
|
# By smell type
|
|
grep "Smell: Long Method" .claude/code-smells.log
|
|
```
|
|
|
|
### Generate Summary Report
|
|
```bash
|
|
# Count by severity
|
|
grep -c "Severity: HIGH" .claude/code-smells.log
|
|
grep -c "Severity: MEDIUM" .claude/code-smells.log
|
|
grep -c "Severity: LOW" .claude/code-smells.log
|
|
|
|
# Most common smells
|
|
grep "Smell:" .claude/code-smells.log | sort | uniq -c | sort -rn
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Customize in `.claude/settings.json`:
|
|
|
|
```json
|
|
{
|
|
"plugins": {
|
|
"rubyist": {
|
|
"codeSmellLogging": {
|
|
"enabled": true,
|
|
"logPath": ".claude/code-smells.log",
|
|
"severityThreshold": "MEDIUM",
|
|
"excludePatterns": [
|
|
"**/*_spec.rb",
|
|
"db/migrate/**",
|
|
"lib/generated/**"
|
|
],
|
|
"autoRefactorSuggestions": true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Integration with Refactoring Workflow
|
|
|
|
The log helps prioritize refactoring:
|
|
|
|
1. **Review accumulated smells** weekly/sprint
|
|
2. **Prioritize by frequency** (same smell in multiple files)
|
|
3. **Track improvements** (smell resolution over time)
|
|
4. **Learn patterns** (recurring issues suggest training needs)
|
|
|
|
## Educational Benefit
|
|
|
|
Over time, the log becomes a learning tool:
|
|
- See which smells occur most frequently
|
|
- Understand which POODR principles need focus
|
|
- Track improvement in code quality
|
|
- Share patterns with team
|
|
|
|
## Privacy Note
|
|
|
|
The log is local to the repository and should be added to `.gitignore` unless team wants to track collectively:
|
|
|
|
```
|
|
# .gitignore
|
|
.claude/code-smells.log
|
|
```
|
|
|
|
Or commit for team awareness:
|
|
```
|
|
# Track team code quality
|
|
!.claude/code-smells.log
|
|
```
|