Refactoring
A thorough reference covering 89 refactoring techniques and code smells — featuring PHP 8.3+ examples, rationale, step-by-step mechanics, and before/after comparisons.
Refactoring Techniques (67)
Composing Methods
-
Extract Method — Pull code fragments into named methods → reference
-
Inline Method — Substitute a method call with its body → reference
-
Extract Variable — Give complex expressions meaningful names through explanatory variables → reference
-
Inline Temp — Substitute a temporary variable with its expression → reference
-
Replace Temp with Query — Swap temp variables for method calls → reference
-
Split Temporary Variable — Assign separate variables for separate purposes → reference
-
Remove Assignments to Parameters — Introduce local variables rather than reassigning parameters → reference
-
Replace Method with Method Object — Convert a complex method into its own class → reference
-
Substitute Algorithm — Swap an algorithm for a clearer alternative → reference
Moving Features Between Objects
-
Move Method — Relocate a method to the class that depends on it most → reference
-
Move Field — Relocate a field to the class that depends on it most → reference
-
Extract Class — Divide a class that handles too much → reference
-
Inline Class — Consolidate a class that does too little → reference
-
Hide Delegate — Introduce methods that conceal delegation chains → reference
-
Remove Middle Man — Allow clients to call the delegate directly → reference
-
Introduce Foreign Method — Attach a missing method to a class you cannot modify → reference
-
Introduce Local Extension — Build a wrapper or subclass for a library class → reference
Organizing Data
-
Self Encapsulate Field — Route field access through getters even within the class → reference
-
Replace Data Value with Object — Promote primitive data to a rich object → reference
-
Change Value to Reference — Convert value objects into reference objects → reference
-
Change Reference to Value — Convert reference objects into value objects → reference
-
Replace Array with Object — Swap arrays used as data structures for proper objects → reference
-
Duplicate Observed Data — Keep domain data in sync with the UI via Observer → reference
-
Change Unidirectional to Bidirectional — Introduce back-references when needed → reference
-
Change Bidirectional to Unidirectional — Eliminate unnecessary back-references → reference
-
Replace Magic Number with Symbolic Constant — Assign meaningful names to magic numbers → reference
-
Encapsulate Field — Restrict field visibility, expose accessors → reference
-
Encapsulate Collection — Expose read-only views of collections → reference
-
Replace Type Code with Class — Swap type codes for enums or classes → reference
-
Replace Type Code with Subclasses — Swap type codes for a class hierarchy → reference
-
Replace Type Code with State/Strategy — Swap behavior-affecting type codes for State/Strategy → reference
-
Replace Subclass with Fields — Eliminate subclasses that differ only in constants → reference
Simplifying Conditional Expressions
-
Decompose Conditional — Break complex conditionals into named methods → reference
-
Consolidate Conditional Expression — Merge conditions that produce the same result → reference
-
Consolidate Duplicate Conditional Fragments — Hoist identical code outside of conditionals → reference
-
Remove Control Flag — Swap control flags for break/return/continue → reference
-
Replace Nested Conditional with Guard Clauses — Flatten nested conditionals using early returns → reference
-
Replace Conditional with Polymorphism — Swap conditionals for polymorphic method calls → reference
-
Introduce Null Object — Swap null checks for a null object → reference
-
Introduce Assertion — Insert assertions to document assumptions → reference
Simplifying Method Calls
-
Rename Method — Choose method names that reveal their purpose → reference
-
Add Parameter — Introduce new parameters to support additional data → reference
-
Remove Parameter — Drop unused method parameters → reference
-
Separate Query from Modifier — Divide methods that both return values and change state → reference
-
Parameterize Method — Unify similar methods by adding a parameter → reference
-
Replace Parameter with Explicit Methods — Produce separate methods for each parameter value → reference
-
Preserve Whole Object — Pass the entire object rather than individual values → reference
-
Replace Parameter with Method Call — Derive values internally instead of passing them in → reference
-
Introduce Parameter Object — Bundle related parameters into an object → reference
-
Remove Setting Method — Eliminate setters for fields assigned only at creation → reference
-
Hide Method — Narrow the visibility of unused public methods → reference
-
Replace Constructor with Factory Method — Use factory methods for complex object creation → reference
-
Replace Error Code with Exception — Throw exceptions rather than returning error codes → reference
-
Replace Exception with Test — Validate conditions upfront instead of catching exceptions → reference
Dealing with Generalization
-
Pull Up Field — Promote identical fields to the superclass → reference
-
Pull Up Method — Promote identical methods to the superclass → reference
-
Pull Up Constructor Body — Promote shared constructor logic to the superclass → reference
-
Push Down Method — Relocate a method to the subclass that uses it → reference
-
Push Down Field — Relocate a field to the subclass that uses it → reference
-
Extract Subclass — Carve out a subclass for a subset of features → reference
-
Extract Superclass — Hoist shared behavior into a parent class → reference
-
Extract Interface — Define a shared interface for common operations → reference
-
Collapse Hierarchy — Merge superclass and subclass when they are too similar → reference
-
Form Template Method — Generalize similar methods into a template → reference
-
Replace Inheritance with Delegation — Swap inheritance for composition → reference
-
Replace Delegation with Inheritance — Swap excessive delegation for inheritance → reference
Code Smells (22)
Bloaters
-
Long Method — Methods that have grown excessively long → reference
-
Large Class — Classes that try to handle too much → reference
-
Primitive Obsession — Excessive use of primitives instead of small objects → reference
-
Long Parameter List — Methods accepting too many parameters → reference
-
Data Clumps — Groups of data that repeatedly appear together → reference
Object-Orientation Abusers
-
Alternative Classes with Different Interfaces — Similar classes with mismatched method signatures → reference
-
Refused Bequest — Subclasses that disregard inherited behavior → reference
-
Switch Statements — Complex switch/match constructs that should be polymorphism → reference
-
Temporary Field — Fields populated only under certain conditions → reference
Change Preventers
-
Divergent Change — A single class modified for many unrelated reasons → reference
-
Parallel Inheritance Hierarchies — Creating one subclass forces creating another → reference
-
Shotgun Surgery — A single change demands edits across many classes → reference
Dispensables
-
Comments — Excessive comments that mask unclear code → reference
-
Duplicate Code — Identical or nearly identical code in multiple locations → reference
-
Data Class — Classes consisting of nothing but fields and getters/setters → reference
-
Dead Code — Unreachable or unused code → reference
-
Lazy Class — Classes that contribute too little to justify their existence → reference
-
Speculative Generality — Unused abstractions built "just in case" → reference
Couplers
-
Feature Envy — Methods that rely more on another class's data than their own → reference
-
Inappropriate Intimacy — Classes that reach into each other's internals → reference
-
Incomplete Library Class — Library classes that fall short of providing needed features → reference
-
Message Chains — Long chains of method calls (a.b().c().d()) → reference
-
Middle Man — Classes that do nothing but delegate to another class → reference
Best Practices
-
Refactor in small, verified steps — execute tests after every change
-
Follow the Boy Scout Rule: leave code in better shape than you found it
-
Reach for IDE refactoring tools when available for safe, automated transformations
-
Never refactor and alter behavior simultaneously — keep them separate
-
Prioritize refactoring that lowers coupling and raises cohesion
-
Tackle code smells nearest to your current work first