Refactoring Priorities
Learn how to prioritize refactoring in TDD. Discover best practices for code improvement and maintenance with TDD Buddy's expert advice.
Here is the order of importance when evaluating potential refactoring opportunities while reflecting on your code.
-
Identify Concepts:
- Consider the Single Responsibility principle of SOLID.
- Each collection of responsibilities should only have one reason to change.
- Group responsibilities at the method level.
- Group responsibilities at the class or concept level.
- Group related methods into new classes.
- Ensure to create a related test class and migrate the affected tests.
- Consider the Single Responsibility principle of SOLID.
-
Name Things Well
- Apply the Stages of Naming to variables, methods, class and test names
- Strive for meaningful names and avoid specific names in tests.
- Apply the Stages of Naming to variables, methods, class and test names
-
Apply the Remaining SOLID Principles
- Open/Closed Principle
- Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification.
- Liskov Substitution Principle
- Subtypes must be substitutable for their base types.
- Interface Segregation Principle
- Clients should not be forced to depend on methods they do not use.
- Dependency Inversion Principle
- Abstractions should not depend on details. Details should depend on abstractions.
- Open/Closed Principle
-
DRY (Don’t Repeat Yourself)
- Every piece of knowledge should have a single, unambiguous, and authoritative representation in the system.
- This principle is often misunderstood, with developers creating abstractions for things that appear similar but represent different concepts.
- Code is only repeated if it represents the same concept. This is true when the same sentence can be used to describe what it represents without ‘and’.
Why this order
The list runs from the changes with the widest effect to the narrowest.
- Concepts come first because every later step depends on them. A good name for a method that mixes two responsibilities is still a name for the wrong thing, and SOLID principles applied to a muddled class only make the muddle more elaborate.
- Naming comes second because once the concepts are separate, names are the main way the next reader (including an AI coding agent) discovers what each one does. Renaming is cheap, safe with tests in place, and pays off every time the code is read.
- The remaining SOLID principles come third because they shape how concepts relate to each other: what can be extended, what can be substituted, and which way dependencies point. That only makes sense once the concepts exist.
- DRY comes last because removing duplication too early merges things that only look alike. Waiting until the concepts and names are clear makes it obvious whether two pieces of code describe the same idea.
Using the list in the refactor step
After each green bar, walk down the list and stop at the first item that applies. Make that one change, run the tests, and walk the list again. If nothing applies, write the next failing test. Small, single-purpose refactorings keep the tests green between steps and make it easy to undo a change that didn’t help.
If you find yourself at step 4 removing duplication between two blocks of code, try the “and” test from above: describe what each block represents in one sentence. If the sentences are the same, extract the shared code. If you need “and” to make one sentence cover both, they are different concepts and should stay separate, even if the code looks identical today.
For more on spotting what to refactor, see Test Smells and SOLID Explained.