Extract and Override
Blog post series
This blog post is part of a series about legacy coderetreat and legacy code techniques you can apply during your work. Please click to see more sessions about legacy code.
Purpose
Almost always when needing to test existing code we bump against dependencies that make the system untestable. This technique is useful to extract the static dependencies. After that we can use dependency inversion in order to be able to really test the systems.
With this technique we can transform untestable systems into testable systems, step by step. The steps are small because we want to enable safety while changing the code.
Clik here to view.

Extract and Override
Concept
If we have static dependencies, the system is very difficult or impossible to test. If we have slow dependencies the tests we write are very slow and we have slow feedback about the system’s health.
Let’s say we have an ugly production code that calls a static reference.
public class Math { public void add(int a, int b){ int result = a + b; System.out.println("The result is " + result); } }
We write a test and run it. The first thing that happens is that we have an exception popping up.
public class MathTests { @Test public void addWithTwoPositiveNumbersWritesCorrectResultToConsole(){ Math math = new Math(); math.add(3,4); // how to test??? } }
The conclusion is that we cannot really test the system like that, having the static dependency. We do not have a method to take the result of the system, because the result is immediately sent to the console, which is the static dependency. So we need to take measures. Here are the steps for extract and override:
Step 1: Create an empty class that inherits from our production class
public class Math { public void add(int a, int b){ int result = a + b; System.out.println("The result is " + result); } } public class MathForTests extends Math { }
Step 2: Extract the static reference to another private method. Test the production code still works
public class Math { public void add(int a, int b){ int result = a + b; consoleWriteline("The result is " + result); } private void consoleWriteline(String message){ System.out.println(message); } } public class MathForTests extends Math { }
Step 3: Make the extracted method protected
public class Math { public void add(int a, int b){ int result = a + b; consoleWriteline("The result is " + result); } protected void consoleWriteline(String message){ System.out.println(message); } } public class MathForTests extends Math { }
Step 4: Change the test to use the inherited class and not the production class
public class MathTests { @Test public void addWithTwoPositiveNumbersWritesCorrectResultToConsole(){ MathForTests math = new MathForTests(); math.add(3,4); // how to test??? } }
Step 5: Override the protected method in the new class that inherits from the production class
public class MathForTests extends Math { @Override protected void consoleWriteline(String message){} }
Step 6: Write the minimum code in order to make the method work
public class MathForTests extends Math { public String messageWritten; @Override protected void consoleWriteline(String message){ messageWritten = message; } }
Step 7: Write the assertion for the test. It is green
public class MathTests { @Test public void addWithTwoPositiveNumbersWritesCorrectResultToConsole(){ MathForTests math = new MathForTests(); math.add(3,4); assertEquals("The result is 7", math.messageWritten); } }
Step 8: Test the production code still works
By using this technique we can easily avoid any static dependencies.
Outcomes
We will be able to write isolated unit tests for an existing system that has static dependencies.
We started from a code that is highly coupled with a static dependency
public class Math { public void add(int a, int b){ int result = a + b; System.out.println("The result is " + result); } }
and we ended with a code where the static dependency is less coupled with the system
public class Math { public void add(int a, int b){ int result = a + b; consoleWriteline("The result is " + result); } protected void consoleWriteline(String message){ System.out.println(message); } }
But this is not enough. If we want to have a better design we need to extract the consoleWriteline function to a new class and apply dependency inversion.
Extract and override is useful to make the system less coupled and more cohesive.
Remarks
After applying extract and override we might want to continue with refactoring the system more. We might want to use dependency inversion in order to have a system where the static dependencies are abstracted and sent as parameters. We will see more how to do this during the next post.
Even though it might seem like a simple technique, we need to focus on taking baby steps.
This technique is useful to try and understand existing code better. You can see how you can improve the code design in order to have a testable design. The changes we made in the production code were minimal, we just extracted a method. This is an essential aspect: we made minimal changes and the production code still works fine.
History
This technique was first explained in the book Working Effectively with Legacy Code by Michael Feathers.
Code Cast
Please find here a code cast in Java about this session
The post Legacy Coderetreat: Part 8 – Extract and Override appeared first on Adrian Bolboaca.