Working Effectively With Legacy Code — Changing Software (Part 1: Chapter 2)
This is Chapter 2 of the Working Effectively With Legacy Code series. If you haven’t read Chapter 1.
Part 1 : Mechanics of Change:
Chapter 2: Working with Feedback
The Legacy Code DilemmaWhen we have to change code, we should have tests in place. To put tests in place, we often have to change code.
Software changes can be made in two primary ways.
- Edit and Pray.
- Cover and modify.
Edit and Pray
Unfortunately, Edit and Pray, is pretty much the industry standard. We carefully plan the changes, modify and run the system to ensure we didn’t break anything. We hope and pray that we got them right.
Cover and Modify
The idea behind Cover and Modify, is that we work with a safety net when we make changes. Covering software means covering it with tests. When we have good set of tests, we can make changes and find out very quickly whether the effects were good or bad.
In Software, traditionally, testing is a process of executing a program or application with the intent of finding the software bugs or test to see if it meets some specification or testing to attempt to show correctness.
The testing conducted by testing team, provides feedback to the development team. This feedback loop is large. This is atypical of system-level regression testing.
Software Vise:
"When we have tests that detect change, it is like having a vise around our code. The behavior of the code is fixed in place. When we make changes, we can know that we are changing only one piece of behavior at a time".
Some different types of testing in software industry are as follows:
- Unit Tests.
- Integration Tests.
- Functional Tests.
- End-to-end tests.
- Acceptance testing.
- Performance testing.
- Smoke testing.
“Unit testing is very important in Legacy Code Work”.
What is Unit Testing?
These are small, localized tests which gives instant feedback to the developer and allow us to refactor with much more safety.
A unit test that takes 1/10th of a second to run is a slow unit test.
In Unit Testing, we are concerned with the most atomic behavioral units of a system. Since, we conduct Unit testing in the smallest unit it, allows us to test in isolation.
Unit test helps us:
- to localized the error.
- execute test in shorter time period.
- find the coverage of the test.
Unit tests run fast. If they don’t run fast, they aren’t unit tests.
P.S. Unit test should not:
- Talk to database.
- Communicate across a network.
- Touch the file system.
- No special configuration setup to run the test.
Dependency is one of the most critical problems in software development. Much legacy code work involves breaking dependencies so that change can be easier.
The Legacy Code Change Algorithm
We can use the following algorithm to make changes in legacy code base.
- Identify change points: Find places where you need to make changes.
- Find test points: Find places where tests can be written.
- Break dependencies: Dependencies are the most obvious impediment to testing.
- Write tests: Writing test for legacy code is different than writing for new code.
- Make changes and refactor: We can use TDD(Test Driven Development) to work in legacy code.
When you break dependencies in legacy code, you often have to make some ugly changes. Some dependencies break cleanly; others end up ugly. If we can cover code around the point we broke the
dependencies, we can clean the ugliness later.
Previous Episode (Part 1: Chapter 1):
Coming Soon:
Working Effectively with Legacy Code: (Part 1: Chapter 3)
References:
- Working Effectively With Legacy Code~ Paperback
- Software testing ~ Wiki
- Different Types of Software Testing ~ Atlassian