- Introduced a comprehensive refactoring guide detailing when and how to plan major refactorings, including a structured planning process and real-world examples. - Created a README for the planning directory, outlining its purpose, document lifecycle, and best practices for creating planning documents.
11 KiB
Refactoring Guide
This guide explains how to plan and execute major refactorings in this project.
When to Plan a Refactoring
Not every code change needs a detailed plan. Create a refactoring plan when:
🔴 Major changes requiring planning:
- Splitting modules into packages (>5 files affected, >500 lines moved)
- Architectural changes (new packages, module restructuring)
- Breaking changes (API changes, config format migrations)
🟡 Medium changes that might benefit from planning:
- Complex features with multiple moving parts
- Changes affecting many files (>3 files, unclear best approach)
- Refactorings with unclear scope
🟢 Small changes - no planning needed:
- Bug fixes (straightforward, <100 lines)
- Small features (<3 files, clear approach)
- Documentation updates
- Cosmetic changes (formatting, renaming)
The Planning Process
1. Create a Planning Document
Create a file in the planning/ directory (git-ignored for free iteration):
# Example:
touch planning/my-feature-refactoring-plan.md
Note: The planning/ directory is git-ignored, so you can iterate freely without polluting git history.
2. Use the Planning Template
Every planning document should include:
# <Feature> Refactoring Plan
**Status**: 🔄 PLANNING | 🚧 IN PROGRESS | ✅ COMPLETED | ❌ CANCELLED
**Created**: YYYY-MM-DD
**Last Updated**: YYYY-MM-DD
## Problem Statement
- What's the issue?
- Why does it need fixing?
- Current pain points
## Proposed Solution
- High-level approach
- File structure (before/after)
- Module responsibilities
## Migration Strategy
- Phase-by-phase breakdown
- File lifecycle (CREATE/MODIFY/DELETE/RENAME)
- Dependencies between phases
- Testing checkpoints
## Risks & Mitigation
- What could go wrong?
- How to prevent it?
- Rollback strategy
## Success Criteria
- Measurable improvements
- Testing requirements
- Verification steps
See planning/README.md for detailed template explanation.
3. Iterate Freely
Since planning/ is git-ignored:
- Draft multiple versions
- Get AI assistance without commit pressure
- Refine until the plan is solid
- No need to clean up intermediate versions
4. Implementation Phase
Once plan is approved:
- Follow the phases defined in the plan
- Test after each phase (don't skip!)
- Update plan if issues discovered
- Track progress through phase status
5. After Completion
Option A: Archive in docs/development/ If the plan has lasting value (successful pattern, reusable approach):
mv planning/my-feature-refactoring-plan.md docs/development/
git add docs/development/my-feature-refactoring-plan.md
git commit -m "docs: archive successful refactoring plan"
Option B: Delete If the plan served its purpose and code is the source of truth:
rm planning/my-feature-refactoring-plan.md
Option C: Keep locally (not committed) For "why we didn't do X" reference:
mkdir -p planning/archive
mv planning/my-feature-refactoring-plan.md planning/archive/
# Still git-ignored, just organized
Real-World Example
The sensor/ package refactoring (Nov 2025) is a successful example:
Before:
sensor.py- 2,574 lines, hard to navigate
After:
sensor/package with 5 focused modules- Each module <800 lines
- Clear separation of concerns
Process:
- Created
planning/module-splitting-plan.md(now indocs/development/) - Defined 6 phases with clear file lifecycle
- Implemented phase by phase
- Tested after each phase
- Documented in AGENTS.md
- Moved plan to
docs/development/as reference
Key learnings:
- Temporary
_impl.pyfiles avoid Python package conflicts - Test after EVERY phase (don't accumulate changes)
- Clear file lifecycle (CREATE/MODIFY/DELETE/RENAME)
- Phase-by-phase approach enables safe rollback
See the complete plan: module-splitting-plan.md
Phase-by-Phase Implementation
Why Phases Matter
Breaking refactorings into phases:
- ✅ Enables testing after each change (catch bugs early)
- ✅ Allows rollback to last good state
- ✅ Makes progress visible
- ✅ Reduces cognitive load (focus on one thing)
- ❌ Takes more time (but worth it!)
Phase Structure
Each phase should:
- Have clear goal - What's being changed?
- Document file lifecycle - CREATE/MODIFY/DELETE/RENAME
- Define success criteria - How to verify it worked?
- Include testing steps - What to test?
- Estimate time - Realistic time budget
Example Phase Documentation
### Phase 3: Extract Helper Functions (Session 3)
**Goal**: Move pure utility functions to helpers.py
**File Lifecycle**:
- ✨ CREATE `sensor/helpers.py` (utility functions)
- ✏️ MODIFY `sensor/core.py` (import from helpers.py)
**Steps**:
1. Create sensor/helpers.py
2. Move pure functions (no state, no self)
3. Add comprehensive docstrings
4. Update imports in core.py
**Estimated time**: 45 minutes
**Success criteria**:
- ✅ All pure functions moved
- ✅ `./scripts/lint-check` passes
- ✅ HA starts successfully
- ✅ All entities work correctly
Testing Strategy
After Each Phase
Minimum testing checklist:
# 1. Linting passes
./scripts/lint-check
# 2. Home Assistant starts
./scripts/develop
# Watch for startup errors in logs
# 3. Integration loads
# Check: Settings → Devices & Services → Tibber Prices
# Verify: All entities appear
# 4. Basic functionality
# Test: Data updates without errors
# Check: Entity states update correctly
Comprehensive Testing (Final Phase)
After completing all phases:
- Test all entities (sensors, binary sensors)
- Test configuration flow (add/modify/remove)
- Test options flow (change settings)
- Test services (custom service calls)
- Test error handling (disconnect API, invalid data)
- Test caching (restart HA, verify cache loads)
- Test time-based updates (quarter-hour refresh)
Common Pitfalls
❌ Skip Planning for Large Changes
Problem: "This seems straightforward, I'll just start coding..."
Result: Halfway through, realize the approach doesn't work. Wasted time.
Solution: If unsure, spend 30 minutes on a rough plan. Better to plan and discard than get stuck.
❌ Implement All Phases at Once
Problem: "I'll do all phases, then test everything..."
Result: 10+ files changed, 2000+ lines modified, hard to debug if something breaks.
Solution: Test after EVERY phase. Commit after each successful phase.
❌ Forget to Update Documentation
Problem: Code is refactored, but AGENTS.md and docs/ still reference old structure.
Result: AI/humans get confused by outdated documentation.
Solution: Include "Documentation Phase" at the end of every refactoring plan.
❌ Ignore the Planning Directory
Problem: "I'll just create the plan in docs/ directly..."
Result: Git history polluted with draft iterations, or pressure to "commit something" too early.
Solution: Always use planning/ for work-in-progress. Move to docs/ only when done.
Integration with AI Development
This project uses AI heavily (GitHub Copilot, Claude). The planning process supports AI development:
AI reads from:
AGENTS.md- Long-term memory, patterns, conventions (AI-focused)docs/development/- Human-readable guides (human-focused)planning/- Active refactoring plans (shared context)
AI updates:
AGENTS.md- When patterns changeplanning/*.md- During refactoring implementationdocs/development/- After successful completion
Why separate AGENTS.md and docs/development/?
AGENTS.md: Technical, comprehensive, AI-optimizeddocs/development/: Practical, focused, human-optimized- Both stay in sync but serve different audiences
See AGENTS.md section "Planning Major Refactorings" for AI-specific guidance.
Tools and Resources
Planning Directory
planning/- Git-ignored workspace for draftsplanning/README.md- Detailed planning documentationplanning/*.md- Active refactoring plans
Example Plans
docs/development/module-splitting-plan.md- ✅ Completed, archivedplanning/config-flow-refactoring-plan.md- 🔄 Planned (1013 lines → 4 modules)planning/binary-sensor-refactoring-plan.md- 🔄 Planned (644 lines → 4 modules)planning/coordinator-refactoring-plan.md- 🔄 Planned (1446 lines, high complexity)
Helper Scripts
./scripts/lint-check # Verify code quality
./scripts/develop # Start HA for testing
./scripts/lint # Auto-fix issues
FAQ
Q: When should I create a plan vs. just start coding?
A: If you're asking this question, you probably need a plan. 😊
Simple rule: If you can't describe the entire change in 3 sentences, create a plan.
Q: How detailed should the plan be?
A: Detailed enough to execute without major surprises, but not a line-by-line script.
Good plan level:
- Lists all files affected (CREATE/MODIFY/DELETE)
- Defines phases with clear boundaries
- Includes testing strategy
- Estimates time per phase
Too detailed:
- Exact code snippets for every change
- Line-by-line instructions
Too vague:
- "Refactor sensor.py to be better"
- No phase breakdown
- No testing strategy
Q: What if the plan changes during implementation?
A: Update the plan! Planning documents are living documents.
If you discover:
- Better approach → Update "Proposed Solution"
- More phases needed → Add to "Migration Strategy"
- New risks → Update "Risks & Mitigation"
Document WHY the plan changed (helps future refactorings).
Q: Should every refactoring follow this process?
A: No! Use judgment:
- Small changes (<100 lines, clear approach): Just do it, no plan needed
- Medium changes (unclear scope): Write rough outline, refine if needed
- Large changes (>500 lines, >5 files): Full planning process
Q: How do I know when a refactoring is successful?
A: Check the "Success Criteria" from your plan:
Typical criteria:
- ✅ All linting checks pass
- ✅ HA starts without errors
- ✅ All entities functional
- ✅ No regressions (existing features work)
- ✅ Code easier to understand/modify
- ✅ Documentation updated
If you can't tick all boxes, the refactoring isn't done.
Summary
Key takeaways:
- Plan when scope is unclear (>500 lines, >5 files, breaking changes)
- Use planning/ directory for free iteration (git-ignored)
- Work in phases and test after each phase
- Document file lifecycle (CREATE/MODIFY/DELETE/RENAME)
- Update documentation after completion (AGENTS.md, docs/)
- Archive or delete plan after implementation
Remember: Good planning prevents half-finished refactorings and makes rollback easier when things go wrong.
Next steps:
- Read
planning/README.mdfor detailed template - Check
docs/development/module-splitting-plan.mdfor real example - Browse
planning/for active refactoring plans