I am currently reading Michael Feather's new book: "Working Effectively With Legacy Code." and its been a pretty good read so far.
Michael tackles a tough topic: How to make changes to existing code, while a) getting the new feature to work and b)leaving the code in a better (or at least no worse) state than before.
When people talk about TDD, XP, Agile, or any of the practices associated with these terms, the discussion and examples are often made in greenfield contexts. It used to be whenever someone said, "but what about existing code that doesn't have tests, what do we do then?" The answers seemed to fall into three categories: 1) Don't do that/you can't use that there 2) Rewrite it 3) It depends/Its different each time/Work with someone who has before.
In a fit of hubris Michael has decided to give some concrete answers to that question. Not suprisingly his advice is not some silver bullet quick fix (I don't have the book in front of me at the moment, but Bob Martin says something to this effect in the forward), but rather smacks of the practical: You can't or don't want to do anything drastic, so gradual improvement is what you should strive for. Michael then sets out to build a systematic approach for doing so.
The message that comes through is that Refactoring, TDD, and the other practices of XP are really hard when working with code that wasn't written that way, and so Michael's book is intended to give concrete advice and examples on how to tackle the situation.
The book has three sections:
Part I is an introduction to the subject matter. This will seem like familiar territory to those who've read books by other Agile writers, but Michael sets the context firmly in legacy coding situation (where he defines legacy code as code not easily modifiable i.e. it doesn't have tests that facilitate change).
Part II is organized as a FAQ where Michael introduces more techniques and "tricks of the trade" in the context of typical situations faced by programmers working with legacy code.
Part III is a collection of techniques for modifying code in this circumstance (those familiar with the structure of books like Martin Fowler's Refactoring or the Gang of Four's Design Patterns should find this section to be similar in style.)
I'm only about a third of the way through (although I did review an early copy, and earned this copy as a result), but I'm already finding useful tidbits and concepts. I am restraining myself from jumping straight to Part III -- although I think that this would be a fine way to read the book -- where I think I will personally gain the most practical benefit from this book.
My overall feeling is that Michael has done a good job distilling some of his experience as a mentor in these situations into a good introduction to the topic. He has started the process of building a concept map and pattern language for working on this type of code, and provided the reader with some important tools to add to their agile toolbox.
I wouldn't necessarily recommend Michael's book as a first Agile book (Kent Beck's XP Explained 2nd edition, the aformentioned Refactoring book, or Beck's TDD by Example book should come first IMHO), but Michael doesn't assume that you've read any of these books. He even provides a chapter on TDD and its use in this context.
Like so many other books that try to distill experience, some of the examples are a bit thin or contrived, and Michael seems to make leaps that really aren't if you done this before. The examples come across less as a proof of the technique and more as an illustration of what is possible. Then again, I don't think the book's goal is to prove that TDD with legacy code is possible so much as to provide those who already know it is with some tools and concepts to facilitate their efforts, so while those new to TDD and refactoring will perhaps be confused at why someone might sprout new classes just to introduce unit tests, I think Michael's reasons come through as one progresses through the book.
My biggest critique is that the book uses a lot of forward references (I like to read cover-to-cover so this is a personal gripe more than anything), but I think that the material is organized properly -- its more a shortcoming of pattern/concept books in general rather than this one in particular.
All in all, I think this is an important entry in the Agile/XP canon, and while no book is going to make you an expert at refactoring without a net, or gradually introducing tests into spaghetti code, Michael does a good job of starting the reader on that journey, and for those already doing these things, a common language and framework for building on their experience.
In short a good book. I recommend it.