Courses

Legacy Code Hero

5 lessons 2 h 56 min 2 sections

Start course Watch on YouTube playlist (external link, opens in new tab)

Markdown version

Approaching Legacy Code with a Test Driven Attitude

The Problem

You have been trying to learn TDD (external link, opens in new tab), and it’s going pretty well, but your code looks horrible. It is really hard to test. Your design skills are lacking, and trying to let TDD drive the design without having design skills can lead to a very problematic, although testable, design of your code.

Objectives

I believe that separating the learning about the core skills of Unit Testing (external link, opens in new tab), TDD, and Design should be separated so that the learner will not feel overwhelmed. This course is a complement to the Art of Unit Testing course I am teaching. This course is specifically dealing with legacy code refactoring skills (external link, opens in new tab), and assumes that you already know how to write unit tests.

Assumed: You already have some experience writing unit tests.

We will also take a look at open source projects and try to see how we would refactor them.

About this course

Roy Osherove describes legacy code (external link, opens in new tab) as code that people are afraid to touch (external link, opens in new tab), and names dependencies as its biggest problem. He covers how to choose which classes to test first (external link, opens in new tab) and how to wrap a system in acceptance and integration tests (external link, opens in new tab) before changing it. The rest of the course shows refactorings such as extract interface (external link, opens in new tab), extract and override (external link, opens in new tab) and instance delegator that create seams (external link, opens in new tab) for fakes (external link, opens in new tab), with code demos that include the open-source BlogEngine.NET project.

Curriculum

Section 1

Starting Out

1 lesson · 50 min

This section is a talk on deciding where to start with legacy code, based on how many dependencies and how much logic each class has and on which code is in active development or causing problems. Roy Osherove argues for covering the system with integration and acceptance tests and an automated build that runs them continuously before refactoring, with unit tests filling in later.

  1. Where Do You Start with Legacy Code? Duration 50:03

    Roy Osherove discusses definitions of legacy code and why dependencies make it hard to change, then sorts classes into four quadrants by their number of dependencies and amount of logic to decide where to start testing. For most teams he recommends starting with the easy classes. He then describes wrapping a web project in smoke, security, load speed and page weight tests, built with TeamCity and FinalBuilder scripts that run Cucumber with Capybara or PhantomJS.

Section 2

Refactoring

4 lessons · 2 h 6 min

This section covers refactorings that make legacy code testable without changing its functionality, including extract interface, extract and override, parameterized constructor, break out method object, adapt parameter, static setters and instance delegator. Two lessons apply instance delegator and extract and override in detail, to a static manager class in BlogEngine.NET and to a login manager that calls static dependencies. The last lesson uses extract and override to write password validation logic with test-driven development.

  1. Refactoring Hardcore Skills Duration 46:58

    Roy Osherove goes through refactoring patterns, many of them from Michael Feathers' book Working Effectively with Legacy Code: extract interface (with a fake email sender and a look at inversion of control containers such as Microsoft's Unity), extract and override, parameterized constructor, break out method object, adapt parameter, static setters on singletons, and instance delegator on a static class from BlogEngine.NET. He closes by saying none of these refactorings can be done without acceptance tests, and that testability and good design are not the same thing.

  2. Instance Delegator Focus Duration 13:44

    In BlogEngine.NET, Roy Osherove looks at the static Send method of a manager class, which scans a new post for links and sends trackbacks or pings, and explains why the static class and the blog settings singleton block extract and override. He copies the method into a non-static version, makes the static method forward to a new instance, and extracts virtual methods such as the enable trackback send check so a testable subclass can override them. He ends with an exercise: write unit tests for when trackbacks and ping backs get sent.

  3. Extract And Override Focus Duration 21:17

    Roy Osherove applies extract and override to a login manager that calls a static logger: the call moves into a protected virtual method with as little logic as possible, which a testable subclass overrides to save the message for the test to check. He extends the example to a logger that throws an exception, a call to a static web service and the machine name, then shows extract and override returning fake objects. He also answers a question on whether extracted methods should be protected or public.

  4. Extract And Override With Validation Logic Duration 43:35

    Roy Osherove explains how to test validation code that combines many rules, using a password validator, by testing each rule separately from the logic that combines them. He introduces extract and override, also called the test specific subclass pattern, with a testable subclass that overrides the current time so a check does not have to wait seven days. He then writes a validator test first, with flags in a testable subclass that set what each rule returns, and tests a single rule method directly using the InternalsVisibleTo attribute.