Ideally Create Test cases for all the functionality that the new feature is going to use. Existing as well as new functionality Sometimes this is not possible Actually in most cases Deal with the devil you know Write the new functionality with TDD Leave the old functionality as it is 2
Extract Method When adding new functionality, write new code in a new method with TDD Call this method from the old code. So even if you can’t test existing code, at least the new code has tests . Separates new code from existing code You may end up with illogical methods Change must be implementable as single sequence of statements otherwise you will have lots of extracted methods . 3
Extract Class When Its harder to create instance of the class you wish to write code into, write the new code in a separate class with TDD Call this class from the old code. So even if you can’t test existing code, at least the new code has tests. Separates new code from existing code You may end up with illogical classes Change must be implementable as single sequence of statements otherwise there will lots of wrap methods . 4
Wrap Method Extract all existing code into a private method call it “existing”. Create “new ” method (created using TDD) Call “existing” and “new” from parent method. Easy to implement but not very clean solution Change must be implementable as single sequence of statements otherwise you will have a lot of wrap methods. 5
Wrap Class Create a new class that calls the existing code. Create newCode method (created using TDD ). Create a method in new class that calls the existing method and new method. Easy to implement Too many level of indirections, not very clean solution Change can be implemented as single sequence of statements otherwise there will lots of wrap methods. 6
Subclassing If the class in question is difficult to mock subclass it Override the the method in question to do requisite behavior U se the subclass in test cases The class in question should be non final Check if you are breaking SRP or LSP. Difficult to implement and maintain as parent class grows and changes. 7
Extract Interface If the class in question is difficult to mock Extract an interface from the class Implement the interface, overriding the method in question U se the interface instead of the class, and inject test cases with fake class Not so clean solution, could be lot of changes 8
Final word What you learnt is very basic understanding of class and method level refactoring You will need understanding of design and architecture to refactor like design and architecture refactoring Try Martin Fowler’s book on refactoring Gang of Four book for design patterns 9