Most of the projects that I’ve been paid for thus far have involved working with a substantial amount of what I would gently term “other people’s code”. I’ve also jumped into these projects at a stage where those involved have started to use the terms “technical debt”, “refactoring”, and even “re-engineering” with increasing frequency.
It’s challenging to work with code that has a history, but I find it to be a lot of fun. (From a 30000 foot view, that is — at any given time when I’m in the thick of it, you will hear me cursing under my breath just like anyone else would be.) I’ve developed my own little arsenal of techniques that I use to get things done in such an environment. (The most useful one is to always remind myself that this is software that has been _successful_, and that it has intrinsic worth, even if I am working in a particularly hacky corner of it.)
Anyhow, a few months ago it occurred to me that it would be great to have a book about this sort of thing; about the mindset you should be in when working with old code, the techniques you can use to mitigate the complexity, etc. It didn’t take much poking around to discover Michael Feathers’ book, and I’m glad I did. This is, in my opinion, one of those books that anyone in a software-related field should read.
While I picked up quite a few little tips from Feathers’ book, there were three major contributions that I considered to be the main ones:
- The definition of ‘legacy code’ as ‘code that is not under test’. By casting the problem of maintaining an older system in this light, Feathers moves the problem from the realm of genericity (our code is hard to work with and we need to do something) to the realm of specificity (our code is hard to work with, so we need to find ways to get it under test.) This gives you a specific problem to attack.
- The identification of the “seam” as the primary concern in a legacy system. A seam is defined as any point in the system where one component may be stubbed out or otherwise decoupled so that you can test an interacting component in isolation. This focus on seams essentially turns your “testing quest” into one of decoupling components from one another, which is (in the opinions of many people much smarter than I) perhaps the most critical precondition for keeping a system maintainable.
- The simple fact that Feathers has obviously been in the trenches himself many times, and that he speaks of the experience not with despair, but with acceptance and even mild amusement. While many software engineers I know would bemoan the idea that the status quo of system development should be a gradual decay towards unmaintainability, it’s pretty obvious that it happens and that this is a thing that all of us will one day have to deal with, as inevitably as death, taxes, and all that sort of thing. Having a respected individual in the field talk about it so frankly is, well, downright comforting, and I find it helpful to recall that I am not alone when stuck trying to disentangle some particularly heinous code-rot.
I could go on, but there’s little need. In summary: I strongly recommend Working Effectively with Legacy Code. This is the sort of book that I intend to read not just once, but once every couple of years or so to keep the lessons fresh in my mind.