Category Archives: Legacy Code

Extract and Override – code cast

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.

Code Cast

This is a code cast in Java.

Extract and Override is a very useful technique to break static dependencies. Whenever we cannot write tests for a piece of code, it is often because we have static dependencies. In the code cast below you can see how to use extract and override having a random number generator very tightly coupled. Because of that, we cannot have the same output for some clear steps. The solution found in this video is to extract the random to a new method and then override the random generator, just for tests. In this way we have predictability for tests.

Dependency Inversion – code cast

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.

Code Cast

This is a code cast in Java.

During this code cast you will see how to use the concept of Dependency Inversion on a legacy code base. Dependency Inversion is one way of transforming a tightly coupled system into a system that has a core and many small external dependencies. These external dependencies can be called also plugins. Read more about this concept in my previous blog post.

Code Cast

To ensure that we have a safety net, let us start with covering the code with some system tests and then write tests on the newly created method. These are also characterization tests, but they are often simpler than the system tests we wrote before. When the new method have been covered by tests, call it from the initial place where the code was copied from. Run all the system tests. At the end do some manual testing to see that everything works fine.

This technique is very useful to have small and safe steps while refactoring. Remember to never cut and paste. Always duplicate the implementation, cover it with tests and then reroute the call to the new code.

Add feature on legacy code – code cast

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.

Code Cast

This is a code cast in Java. We have a new feature request and we need to add it to a legacy code base.

We start by understanding what we need to change. After that we run the existing system tests, that we wrote during the session From Nothing to System Tests. We use a test coverage tool to understand how much of the code is covered with tests. After this step we start writing new system tests until all the code
that will be changed is covered by tests.

When all of the system is covered with tests, we refactor the code to make room for a new feature. We extract a method, then a class and then an interface. The interface is implemented in a new way so that we add the new functionality. Adding the new functionality is done with tests written up-front.

At the end we write one system test to verify that the whole system can work well with the new feature. This is a kind of partial acceptance test that helps us understand if all the system works well together. And of course, manual testing and refactoring is essential before we can say we are done.

Document possible Defects with Tests

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

When writing unit tests on legacy code, we often discover behaviours of the system that seem wrong. The main rule is: DO NOT change the production code without being absolutely sure that the change does not introduce defects. Instead we need to mark all the tests that characterize a possible defective behaviour. Let’s look at some ways to document possible defects with tests.

Unit Testing on Legacy Code

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

In the previous episode post we extracted a class. The code we just extracted is tested at this moment only with System Tests. Now it’s the time to start writing unit tests, considering that we already have some system tests in place.

Extract Class

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

When working with existing code we need to look at the responsibilities of existing classes. If one class is too big, we need to extract new classes from that initial class. A class too big means that it’s not respecting the Single Responsibility Principle.

Rule of Three

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

The rule of three says:

Extract duplication only when you see it the third time.

This concept is extremely useful when you want to improve legacy code, refactor in the TDD cycle or just improve existing code that is covered by tests.

The Rule of Three brings higher coherence and more clarity to the system, because the duplicated code starts to be moved into specialized areas. In this way we optimize the code base for changeability.

The Rule of Three prevents from prematurely extracting possible duplication and defers the duplication minimization until we have enough proof.

Extract Pure Functions

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

We have some class that is very big. We want to divide the existing code into more methods and classes so that we have in the end some code that is easier to understand. If the methods are small, they are easy to change. In the same time the code would respect the Single Responsibility Principle. We optimize our software for changeability. In the following we will see how we can extract pure functions to achieve that.