Working Effectively with Legacy Code – Part 2

This week we covered chapters three and four — Sensing and Separation and The Seam Model — of Working Effectively with Legacy Code by Michael Feathers.

Sensing and Separation

  • This statement strongly resonated with Houston: “One of the big problems that we confront in legacy code work is dependency.” This is one of the hardest things he comes across when he starts testing something.
  • “A fake object is an object that impersonates some collaborator of your class when it is being tested.” I’ve sometimes heard these called stubs as well.
  • Jamie said the Go language just introduced a file system interface so unit tests could pass. You’re testing whether the code is interacting with the file system, not testing the file system itself.

The Seam Model

  • Houston, Jared, and Geoff used this concept quite a bit at a previous .NET job: “This seam is what I call an object seam. We were able to change the method that is called without changing the method that calls it.”
  • “One of the things that nearly everyone notices when they try to write tests for existing code is just how poorly suited coding is to testing.” We talked about different interpretations of object-oriented programming — e.g., an object controls all of its state vs. inverting dependencies.
  • “When I got out in the industry, I started to care a lot about [modularity], but in school, a program was just a listing to me, a long set of instructions that I had to write and understand one by one.” Same. Jared sees this a lot in the assignments he grades as a computer science TA.
  • “We are often told it is better to write programs that are made of small reusable pieces, but how often are small pieces used independently?” Jamie mentioned a concept from John Degoes: Making things more modular doesn’t really matter if you never put them together differently.
  • Jamie also talked about physical design, where objects have a single way to be put together (https://quality-one.com/dfmea/). We don’t always apply this to software applications (e.g., not always depending on SSL 1.0, planning for any ERP instead of just Oracle).
  • His first example of a seam is the extract and override approach I learned from Roy Osherove’s book The Art of Unit Testing.
  • Terminology
    • Seam — a place where you can alter behavior in your program without editing in that place.
    • Enabling point — a place where you can make the decision to use one behavior or another
  • The concept of a link seam — where you at linkage time swap out the “real” library for a test one — initially had me thinking “but why?”; it makes sense, though, if that’s the only tool in your toolbox. It turns out that Jared, Jamie, Houston, and I have actually have done this; we just didn’t know what it was called. 🙂 There are some other examples of how to debug things in production using a similar technique.
  • The code example of a call that isn’t a seam (i.e., a Java method instantiating a helper class and then using that instance) is the classic example of a violation of the dependency inversion principle. See also: new is glue.
  • Houston liked the author’s example of the object seam; very applicable and easy to understand.