Overview
This directory contains real-world refactoring examples demonstrating how to improve code quality, maintainability, and adherence to the style guide principles. Each example shows before/after code with detailed explanations of the refactoring patterns applied.
What is Refactoring?¶
Refactoring is the process of restructuring existing code without changing its external behavior. The goal is to improve:
- Readability: Make code easier to understand
- Maintainability: Reduce technical debt and complexity
- Performance: Optimize execution efficiency
- Testability: Make code easier to test
- Reusability: Extract common patterns
- Security: Remove vulnerabilities
Refactoring vs. Rewriting¶
| Refactoring | Rewriting |
|---|---|
| Incremental changes | Complete replacement |
| Preserves functionality | May change functionality |
| Lower risk | Higher risk |
| Continuous improvement | One-time effort |
| Maintain tests | Rebuild tests |
When to Refactor¶
Good Times to Refactor¶
✅ During feature development - Boy Scout Rule (leave code better than you found it) ✅ Before adding new features - Clean up the area you'll be working in ✅ During code review - Address technical debt discovered ✅ When fixing bugs - Improve code structure to prevent similar bugs ✅ Regular maintenance - Scheduled refactoring sessions
Avoid Refactoring When¶
❌ Under tight deadlines - Unless refactoring makes the deadline easier to meet ❌ Broken code - Fix functionality first, then refactor ❌ No tests - Add tests before refactoring ❌ Unclear requirements - Clarify expectations first
Common Refactoring Patterns¶
Code Organization¶
- Extract Function: Break large functions into smaller, focused ones
- Extract Class: Move related functionality into a dedicated class
- Inline Function: Remove unnecessary abstraction layers
- Move Method: Relocate methods to more appropriate classes
Code Clarity¶
- Rename: Use descriptive, meaningful names
- Replace Magic Numbers: Use named constants
- Simplify Conditionals: Reduce complexity of if/else logic
- Remove Dead Code: Delete unused code
Code Structure¶
- Replace Conditional with Polymorphism: Use inheritance instead of type checking
- Introduce Parameter Object: Group related parameters
- Preserve Whole Object: Pass objects instead of individual fields
- Replace Temp with Query: Replace temporary variables with method calls
Code Quality¶
- Decompose Conditional: Break complex conditionals into well-named functions
- Consolidate Duplicate Code: Apply DRY principle
- Simplify Method Chains: Reduce coupling and improve readability
- Replace Nested Conditional with Guard Clauses: Early returns for error cases
Refactoring by Language¶
This directory includes language-specific refactoring examples:
Python Refactoring¶
- Extract function from long method
- Replace magic numbers with constants
- Simplify complex conditionals
- Use comprehensions effectively
- Apply type hints
TypeScript Refactoring¶
- Extract components from monolithic files
- Replace any with proper types
- Simplify async/await chains
- Use modern ES6+ features
- Apply functional programming patterns
Terraform Refactoring¶
- Extract reusable modules
- Simplify variable structures
- Use for_each instead of count
- Apply locals for DRY
- Improve resource naming
Ansible Refactoring¶
- Extract roles from playbooks
- Use blocks for error handling
- Apply handlers effectively
- Simplify conditionals
- Use collections
Bash Refactoring¶
- Extract functions from scripts
- Add error handling
- Use arrays instead of strings
- Apply POSIX compliance
- Improve variable quoting
Refactoring Workflow¶
1. Ensure Tests Exist¶
## Run existing tests before refactoring
pytest tests/
npm test
terraform test
If no tests exist: Write tests first to ensure refactoring doesn't break functionality.
2. Make Small, Incremental Changes¶
- One refactoring at a time
- Commit after each successful refactoring
- Run tests after each change
3. Use Automated Tools¶
- Python:
black,isort,pylint,mypy - TypeScript:
prettier,eslint,tsc --strict - Terraform:
terraform fmt,tflint,terrascan - Ansible:
ansible-lint,yamllint - Bash:
shellcheck,shfmt
4. Code Review¶
- Peer review refactored code
- Ensure changes are understood
- Verify tests pass in CI/CD
5. Document Rationale¶
## Good commit message
refactor: extract user validation into separate function
Moved user input validation from main() into validate_user()
to improve testability and reusability. Reduces main() function
complexity from 150 to 80 lines.
Closes #123
Measuring Refactoring Success¶
Code Metrics¶
- Cyclomatic Complexity: Lower is better (aim for < 10 per function)
- Lines per Function: Smaller functions (aim for < 50 lines)
- Code Duplication: Reduce duplicate code (aim for < 5%)
- Test Coverage: Maintain or improve (aim for > 80%)
Tools for Measurement¶
- Python:
radon,pylint,coverage - TypeScript:
complexity-report,istanbul,sonarqube - Terraform:
terraform validate,tflint - General:
sonarqube,code-climate
Best Practices¶
- Test First: Always have tests before refactoring
- Small Steps: Make incremental changes
- Commit Often: Checkpoint after each successful refactoring
- Code Review: Get feedback on refactoring decisions
- Document Why: Explain the reasoning behind changes
- Measure Impact: Track improvements with metrics
- Avoid Scope Creep: Stick to one refactoring pattern at a time
- Preserve Behavior: Don't mix refactoring with feature changes
Anti-Patterns to Avoid¶
❌ Big Bang Refactoring: Rewriting large portions of code at once ❌ Refactoring Without Tests: Changing code without safety net ❌ Premature Optimization: Refactoring before understanding performance needs ❌ Over-Engineering: Adding unnecessary abstraction ❌ Mixing Concerns: Refactoring and adding features simultaneously ❌ Ignoring Style Guide: Refactoring without following project standards
Resources¶
Books¶
- Refactoring: Improving the Design of Existing Code by Martin Fowler
- Clean Code by Robert C. Martin
- Working Effectively with Legacy Code by Michael Feathers
Online Resources¶
- Refactoring Guru - Refactoring patterns and examples
- Source Making - Design patterns and refactorings
- Code Smells - Identifying code that needs refactoring
Related Documentation¶
- Anti-Patterns - Common mistakes to avoid
- Language Guides - Language-specific best practices
- Examples - Complete project examples
- Testing Strategies - Testing approaches for refactored code
Maintainer: Tyler Dukes