Legacy Coderetreat: Part 8 – Extract and Override

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.

Extract and Override

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.

We write a test and run it. The first thing that happens is that we have an exception popping up.

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

Step 2: Extract the static reference to another private method. Test the production code still works

Step 3: Make the extracted method protected

Step 4: Change the test to use the inherited class and not the production class

Step 5: Override the protected method in the new class that inherits from the production class

Step 6: Write the minimum code in order to make the method work

Step 7: Write the assertion for the test. It is green

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

and we ended with a code where the static dependency is less coupled with the system

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

Subscribe

If you want to receive an email when I write a new article, subscribe here:

Subscribe for new articles

2 Thoughts on “Legacy Coderetreat: Part 8 – Extract and Override

  1. Great post! I like how you described the technique in little steps, keeping the process as mechanical and safe as possible. I use this technique all the time when I’m working with untested code and it’s easy to understand once you’ve seen it in action.

    I recently had a discussion with a teammate regarding “test induced damage” when applying this technique to legacy code. He argued that these techniques to get code under test needlessly complicate the production code (even more so when you introduce a new abstraction and apply dependency inversion). What are your counter arguments when faced with this?

    • Hi Jo, thanks for the comment.

      As you can see in my following blog post http://blog.adrianbolboaca.ro/2015/01/use-mocking-framework the technique Extract and Override is just a step towards decoupling two parts of the system. As I am mentioning there as well, there is a cost in introducing abstractions and integration layers. But this cost is usually payed for having a system that is easier to change and easier, or possible, to test.

      I can agree that in the end we have more code constructs, and that understanding each interface or class we add can take some energy. But in the same time the small classes that we have in the end are not complicated. They are basic, trivial classes that anyone can understand. We complicate a bit the way they collaborate. But in fact it is not a complication, because they collaborated anyway. We just make visible a hidden complexity.

      So all design decisions come with costs. We have to put into balance pros and cons and decide what to do.
      Plus: testable design, changeable system.
      Minus: more code constructs.

      For me the balance is on Plus. I want a testable and changeable system. But for you, in your case it might be different. You need to think and take informed and non-emotional decisions.

Leave a Reply

Your email address will not be published. Required fields are marked *

Post Navigation