Extract and Override

This is a classic dependency breaking technique from Michael Feathers’ book “Working Effectively with Legacy Code”. In this session we learn how to use it on the classic coding problem “TripService” by Sandro Mancuso. Emily Bache has made a video “Breaking Legacy Code Dependencies with Extract and Override” that explains more and shows a demo using Java.

In Legacy Code we can often times find usages of the Singleton pattern or static method calls to infrastructure functionality scattered around the code. This makes it very hard to try to test these kind of methods. Most of the time, it is not easily possible to change the constructor to inject these services or change the method signature without breaking other code. We still would like to get these methods into a test harness.

Learning Objectives

Session Outline

Connect - Safe Refactorings for Breaking Dependencies

Make a list of names of refactorings, most of which people should have heard of and know roughly what they do. Ask them to vote for which ones they would feel confident doing without having any unit tests. When everyone has voted, summarize what the majority of people think would be ok. Point out it’s about risk. Some refactorings are more risky because you might make a mistake. Some are less risky because they are simpler to get right, or because you have good deterministic tools.

Sample list of refactorings to vote on:

Concept - What is a Dependency Breaking Technique

Use the chapter from Feathers’ book as a basis for presenting what this is.

“Dependency-Breaking Techniques… decouple classes well enough to get them under test” – Michael Feathers, introduction to chapter 25 in “Working Effectively with Legacy Code”

You could mention that there are 24 such techniques listed and today we will look at one of the simplest ones - Extract and Override.

Concept - Demo

In the Trip Service Kata, show how to use ‘Extract and Override’ to make the code testable. It is hard to test the getTripsByUser method, because it uses a Singleton UserSession and a database call TripDAO.findTripsByUser. We cannot easily inject those dependencies without changing the external interface of TripService.

Note - this demo is shown between timestamps 1:43 - 5:21 of the video.

Concrete Practice - Trip Service Kata

Give them the goal to repeat what you showed in the demo, and continue to use the ‘Extract and Override’ technique to handle the TripDAO.findTripsByUser dependency. They should write unit tests for these three scenarios:

Encourage them to do the first one by hand, and after that they can use an AI tool if they want to.

If they complete these three tests quickly, ask them to use the same approach to solve another, similar exercise, for example:

Conclusions - When should you use this

Get people to discuss when to use dependency breaking techniques. You could also ask about any drawbacks they see with the “Extract and Override” dependency breaking technique.