
refactoring-protocol
by PROdotes
MP3 library manager and auto player
SKILL.md
name: Refactoring Protocol description: Safe, systematic approach to code refactoring with verification and rollback strategy.
Refactoring Protocol
This skill enforces disciplined refactoring practices to improve code quality without breaking functionality.
The Prime Directive
"Working Code is Sacred"
- NEVER refactor without tests verifying current behavior
- NEVER refactor and add features simultaneously
- NEVER proceed if tests fail after refactoring
- If stuck, REVERT IMMEDIATELY (do not stack fixes on broken code)
Phase 1: Assessment & Planning
Step 1.1: Identify Refactoring Need
Common triggers:
- God Object: File > 600 lines
- Duplicate Code: Same logic in multiple places
- Architectural Violation: SQL in UI, business logic in repository, etc.
- Poor Naming: Unclear variable/method names
- Deep Nesting: If/else/for blocks > 3 levels deep
- Long Methods: Functions > 50 lines
- Feature Envy: Class A uses Class B's data more than its own
Step 1.2: Capture Current Behavior
- Run Existing Tests: Ensure all tests pass BEFORE starting
python tools/run_tests.py - Document Current Behavior: If no tests exist, write them first
- Create Reproduction Script if needed (for complex scenarios)
Step 1.3: Plan the Refactoring
- Define the Goal: What will be better after refactoring?
- Identify Risk Areas: What could break?
- Plan Small Steps: Break into incremental changes
- Present Plan to User: Get approval before starting
Phase 2: Execution (The Refactoring Steps)
General Principles
- One Change at a Time: Rename OR extract OR move, not all three
- Keep Tests Green: Run tests after each step
- Commit Each Step: Small, atomic commits (though user controls when)
Common Refactoring Patterns
Pattern A: Extract Method
When: Method > 50 lines or does multiple things
Steps:
- Identify block of code to extract
- Determine required parameters and return value
- Create new method with descriptive name
- Move code to new method
- Replace original code with method call
- Run tests
Example:
# BEFORE
def process_song(self, file_path: str):
# 20 lines of file validation
if not os.path.exists(file_path):
raise FileNotFoundError(...)
if not file_path.endswith('.mp3'):
raise ValueError(...)
# ... more validation
# 30 lines of metadata extraction
audio = MP3(file_path)
title = audio.get('TIT2')
# ... more extraction
# AFTER
def process_song(self, file_path: str):
self._validate_file(file_path)
metadata = self._extract_metadata(file_path)
# ...
def _validate_file(self, file_path: str):
# Validation logic here
def _extract_metadata(self, file_path: str) -> dict:
# Extraction logic here
Pattern B: Extract Class
When: Class > 600 lines or has multiple responsibilities
Steps:
- Identify cohesive group of methods/attributes
- Create new class
- Move methods/attributes to new class
- Update original class to delegate to new class
- Update all references
- Run tests
Example:
# BEFORE
class LibraryWidget: # 800 lines
def filter_by_artist(self): ...
def filter_by_genre(self): ...
def apply_complex_filter(self): ...
# ... 20 more filter methods
# ... plus 30 other widget methods
# AFTER
class LibraryWidget: # 400 lines
def __init__(self):
self._filter_manager = FilterManager()
def apply_filter(self, filter_spec):
self._filter_manager.apply(filter_spec)
class FilterManager: # New class, 300 lines
def filter_by_artist(self): ...
def filter_by_genre(self): ...
def apply_complex_filter(self): ...
Pattern C: Move Method (Layer Correction)
When: Method is in wrong architectural layer
Steps:
- Create method in correct layer
- Update original method to delegate (temporarily)
- Update all callers to use new location
- Delete old method
- Run tests
Example:
# BEFORE - SQL in UI layer (VIOLATION)
class LibraryWidget:
def load_songs(self):
cursor.execute("SELECT * FROM songs") # WRONG LAYER!
# AFTER - SQL in Repository
class SongRepository:
def get_all(self) -> List[Song]:
cursor.execute("SELECT * FROM songs") # CORRECT LAYER
return [self._row_to_song(row) for row in cursor.fetchall()]
class LibraryService:
def get_all_songs(self) -> List[Song]:
return self._song_repo.get_all()
class LibraryWidget:
def load_songs(self):
songs = self._library_service.get_all_songs() # CORRECT
Pattern D: Rename (Clarity Improvement)
When: Names are unclear or misleading
Steps:
- Use IDE's rename refactoring OR grep to find all usages
- Rename in all locations
- Run tests
- Update related documentation
Example:
# BEFORE
def proc(self, d): # Unclear
return d.get('val')
# AFTER
def extract_title(self, metadata: dict) -> str: # Clear
return metadata.get('title')
Pattern E: Introduce Parameter Object
When: Function has > 4 parameters
Steps:
- Create dataclass for parameters
- Update function signature
- Update all call sites
- Run tests
Example:
# BEFORE
def create_song(self, title, artist, year, genre, bpm, isrc):
pass
# AFTER
@dataclass
class SongCreationData:
title: str
artist: str
year: Optional[int] = None
genre: Optional[str] = None
bpm: Optional[int] = None
isrc: Optional[str] = None
def create_song(self, data: SongCreationData):
pass
Phase 3: Verification
Step 3.1: Test Suite Validation
# Run full test suite
python tools/run_tests.py
# If any tests fail:
# 1. DO NOT PROCEED
# 2. Analyze failure
# 3. If it's a test issue, fix test
# 4. If it's a refactoring issue, REVERT
Step 3.2: Manual Smoke Testing
- Test Main Workflows: Import song, play song, edit metadata, etc.
- Test Edge Cases: Empty library, invalid files, cancellations
- Visual Inspection: UI looks correct, no layout issues
Step 3.3: Performance Check
- Compare Before/After: Did refactoring affect performance?
- Profile Hot Paths: Use cProfile if concerned
- If Slower: Consider optimizing or reverting
Phase 4: The Hard Revert Rule
When to Revert
- Tests fail and root cause is unclear
- Refactoring is taking too long (> 1 hour)
- Discovering unexpected dependencies
- User requests to stop
How to Revert
# Discard all changes
git checkout .
# Or revert specific file
git checkout -- path/to/file.py
After Reverting
- Analyze What Went Wrong: Why did it fail?
- Plan Smaller Steps: Break into even smaller increments
- Ask User: Should we try a different approach?
Phase 5: Completion
Step 5.1: Documentation Updates
- Update comments if method signatures changed
- Update ARCHITECTURE.md if patterns changed
- Update docstrings if behavior clarified
Step 5.2: Checkpoint Reminder
- Remind User to Commit:
"Refactoring complete and verified. Tests pass. Please commit when ready."
- Suggest Commit Message:
refactor(domain): Brief description - Extract FilterManager from LibraryWidget (800 -> 400 lines) - Move SQL queries from UI to SongRepository - No functional changes Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Refactoring Safety Checklist
Before starting:
- ✅ All tests pass
- ✅ User approves refactoring plan
- ✅ Architectural goal is clear
During refactoring:
- ✅ Making one type of change at a time
- ✅ Tests pass after each step
- ✅ Not adding features simultaneously
After completion:
- ✅ All tests still pass
- ✅ No new warnings or errors
- ✅ Code is clearer/cleaner than before
- ✅ No performance regression
Common Refactoring Anti-Patterns
❌ Big Bang Refactoring
Don't refactor entire codebase at once. Small, incremental changes.
❌ Refactoring Without Tests
Always have tests verifying current behavior first.
❌ Refactoring + Feature Addition
Never mix refactoring with new functionality. Refactor first, then add feature.
❌ Premature Abstraction
Don't create abstractions until you have 3+ similar cases.
❌ Ignoring Test Failures
If tests fail, STOP. Don't continue with "I'll fix it later."
❌ Silent Behavior Changes
Refactoring should NOT change behavior. If it does, it's not refactoring.
Example Walkthrough
Scenario: LibraryService is 850 lines and growing
Phase 1: Assessment
- Identify: God Object (> 600 lines)
- Current behavior: All tests pass
- Plan: Extract playlist-related methods to
PlaylistService
Phase 2: Execution
- Create
src/business/services/playlist_service.py - Move
create_playlist()method → Test - Move
add_to_playlist()method → Test - Move
remove_from_playlist()method → Test - Update
LibraryServiceto delegate toPlaylistService - Update all UI callers
Phase 3: Verification
- Run full test suite → All pass
- Manual test: Create playlist, add songs → Works
- Check file sizes:
LibraryServicenow 620 lines,PlaylistService180 lines
Phase 4: Completion
- Remind user to commit
- Suggest: "refactor(services): Extract PlaylistService from LibraryService"
スコア
総合スコア
リポジトリの品質指標に基づく評価
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
レビュー
レビュー機能は近日公開予定です