CRITICAL RULE: When refactoring or modularizing code:
- NO backward compatibility shims
- NO deprecation warnings
- NO legacy method wrappers
- Clean break approach only
- Backward compatibility adds technical debt
- Legacy code paths increase complexity and maintenance burden
- Clean breaks force updates and prevent fragmented codebases
- All code should use the current, best structure
When modularizing or restructuring:
- Create new modular structure with clear separation of concerns
- Delete old files completely - no leaving "deprecated" files around
- Update ALL imports across the entire codebase immediately
- Update ALL tests to use new imports
- Update ALL documentation (AGENTS.md, README.md, docstrings)
- Run full test suite to ensure nothing breaks
- Commit as single atomic change with clear migration notes in commit message
Maximum file length: 600 lines (excluding docstrings)
When to split a file:
- Multiple independent classes/functions that could be separate modules
- Mixed concerns that would benefit from separation
- File exceeds 600 lines of actual code
How to split:
old_module.py (835 lines)
↓
new_structure/
├── __init__.py (exports all public API)
├── base.py (base classes, ~100 lines)
├── component_a.py (~250 lines)
├── component_b.py (~200 lines)
└── component_c.py (~200 lines)
Before refactoring, search for all imports:
grep -r "from old_module import" .
grep -r "import old_module" .After refactoring, update all imports:
- Infrastructure modules
- Test files
- Scripts
- Documentation examples
Update in this order:
- Module docstrings in files
__init__.pyexports with clear APIAGENTS.mdwith new architectureREADME.mdwith new import examples- Any inline code examples in documentation
- Before: Ensure 100% test coverage of code being refactored
- During: Update tests to import from new locations
- After: Run full test suite with coverage report
- Verify: No broken imports, all tests pass
Bad (backward compatibility approach):
# old_api.py
import warnings
from new_module import *
warnings.warn("Use new_module instead", DeprecationWarning)Good (clean break approach):
# Delete old_api.py completely
# Update all imports:
# OLD: from old_api import Thing
# NEW: from new_module.things import Thingrefactor: modularize [module_name] into focused submodules
BREAKING CHANGE: Split [old_file.py] into [new_structure/]
- Created new modular structure with clear separation
- Moved [Component A] to [new_location]
- Moved [Component B] to [new_location]
- Updated all imports across codebase
- Updated all tests
- Updated documentation (AGENTS.md, README.md)
- All tests passing with maintained coverage
Migration guide:
- OLD: from module.old import Thing
- NEW: from module.new.things import Thing
Before marking refactoring:
- New modular structure created
- Old file(s) deleted completely
- All infrastructure imports updated
- All test imports updated
- All script imports updated
- All documentation examples updated
-
__init__.pyexports public API clearly - AGENTS.md reflects new structure
- README.md has updated examples
- Full test suite passes
- Test coverage maintained or improved
- No linter errors introduced
- Commit message documents migration
- Clarity: Only one way to import things
- Maintainability: No legacy code paths to maintain
- Performance: No deprecation warnings at runtime
- Quality: Forces updates
- Documentation: Documentation stays current
- Testing: Tests reflect actual usage
- Simplicity: Codebase easier to understand
- Development Standards — Rule index
- Rules AGENTS — Rules for AI agents