← Back to list

What can be learned from Chapter Two of the “Working Effectively with Legacy Code” book?

Hi All, In this article, I wish to share what I learned by referring to the book called “Working Effectively with Legacy Code. So let’s get…

Heshan Umayanga · 2026-04-30 19:21 · 0 claps · 3.3 min read
#working-with-legacy-code #legacy-code-modernization
Open on Medium ↗

What can be learned from Chapter Two of the “Working Effectively with Legacy Code” book?

Hi All, In this article, I wish to share what I learned by referring to the book called “Working Effectively with Legacy Code. So let’s get started.

I’m on chapter 2, and I came to know a term called “Edit and pray”, which I’ve not heard before, and it has a meaning change and pray for the best.

In the fast-paced world of software engineering, we often obsess over “clean code,” “architecture,” and the latest frameworks. But Michael Feathers, in his seminal work Working Effectively with Legacy Code, argues that there is something far more fundamental that determines the long-term survival of a project: The Feedback Loop.

Specifically, in Chapter 2, titled “The Feedback Loop,” Feathers explores the mechanics of how we change software. If you’ve ever pushed code and then sat there with a knot in your stomach, hoping nothing breaks, this chapter was written for you.

The Two Worlds of Software Change

Feathers categorises the way we approach code modifications into two distinct philosophies. Understanding which one you inhabit is the first step toward professional growth.

1. Edit and Pray

This is, unfortunately, the industry standard. In this world, you plan your change carefully, you write the code, and then you “pray” that it works. You might do some manual smoke testing or wait for a QA report, but the actual feedback is slow and disconnected.

  • The Trap: It relies on human perfection. As the system grows, the “prayer” gets longer because the ripple effects of a single change become impossible to predict mentally.
  • The Cost: It leads to Fear-Driven Development. When you are afraid to touch a piece of code, that code begins to rot.

2. Cover and Modify

This is the professional’s path. Before you touch a single line of functional code, you “cover” it with a test harness.

  • The Goal: To get a notification within seconds if your change broke existing behaviour.
  • The Result: You move from a state of anxiety to a state of confidence. You aren’t guessing anymore; you are observing facts.

Redefining “Legacy Code”

Perhaps the most disruptive insight from Feathers is his functional definition of legacy code. He moves away from age, language, or “clunky” syntax and focuses entirely on safety:

“Legacy code is simply code without tests.”

I already mentioned this in chapter one. This is a wake-up call for many. It doesn’t matter if you wrote a microservice yesterday using the latest Spring Boot or Angular features; if you cannot change it and get immediate feedback on whether it’s broken, you are working with legacy code. Without tests, the code is “dead” because it cannot be safely evolved — it can only be patched.

The Power of the “Sub-Second” Feedback Loop

Why are automated tests so vital? It isn’t just about finding bugs; it’s about cognitive load.

Imagine you make a logic error in a complex algorithm:

  • In an “Edit and Pray” environment, you might find out in 3 days when a bug report comes from production. By then, you’ve lost the context. You have to spend hours re-learning that part of the system just to fix your own mistake.
  • In a “Cover and Modify” environment, your unit tests tell you in seconds. Since the change is fresh in your mind, the fix takes moments.

This speed changes your relationship with the code. When feedback is instant, you are willing to refactor and clean up “smelly” code. When feedback is slow, you become a “feature-adder” who is terrified of cleaning up the mess.

Sensing and Separation: The Mechanics of Testing

Feathers explains that to get code under a test harness, you need two things:

  1. Sensing: The ability to see the effects of your code (values, state changes) that aren’t usually visible.
  2. Separation: The ability to take a piece of code out of its production environment (away from the real database or live API) and run it in a test environment.

This leads to the Legacy Code Dilemma: To put tests in place, you often have to change code. But to change code safely, you need tests. The rest of the book provides the “breaking dependency” patterns to solve this catch.

As developers, our job isn’t just to write features; it’s to manage the evolution of a system. If your primary strategy for change is “Edit and Pray,” you are building a house of cards.

By shifting to a “Cover and Modify” mindset, you aren’t just writing tests — you are building a feedback loop that allows your software to live, grow, and improve without the constant shadow of fear.

I think this content is enough for chapter 2, what I gained from the book. I learn a lot, and I wish you too. I personally think reading a book related to Software Engineering is a much better option than LLM-generated code or YouTube tutorials.


메타데이터
post_id
6eead4a40b9d
slug
what-can-be-learned-from-chapter-two-of-the-working-effectively-with-legacy-code-book-6eead4a40b9d
url
https://medium.com/@heshanu97/what-can-be-learned-from-chapter-two-of-the-working-effectively-with-legacy-code-book-6eead4a40b9d
canonical_url
https://medium.com/@heshanu97/what-can-be-learned-from-chapter-two-of-the-working-effectively-with-legacy-code-book-6eead4a40b9d
author_url
https://medium.com/@heshanu97
status
ok
fetched_at
2026-08-24 23:48:21