Disappointing
|
This book discusses applying refactoring at a level of abstraction above that discussed in Martin Fowler's Refactoring book: packages, subsystems, and layers. It is assumed that the reader has either read the Refactoring book or is familiar with the automated refactoring support offered by modern IDEs. However, a brief introduction is given to refactoring for the uninitiated. Code examples are all in Java.
The book proper commences with a discussion of software architecture smells. These are similar to, but not as plentiful or as well described, as the code smells in the Fowler book. A lot of the code smells from the Fowler book can be applied directly: once you know that cyclic dependencies between classes are bad, you'll be unsurprised to discover that they're also bad between packages. And between subsystems. And layers.
The fourth chapter covers large refactorings. Again, there is not much here that isn't obvious from the smaller scale refactorings from Fowler, just scaled up. Large refactorings need to be broken down into smaller refactorings. Some of these steps may make the design of the software worse, not better. As a result you need to be careful about scheduling the change and knowing if you're making things worse. I did not gain much insight. Examples are given in this chapter, but they're normally at the level of the smaller steps, e.g. renaming a method. There is quite a good example of refactoring a list class hierarchy in a good and a bad way, in terms of the amount of breakage and how easy it is to deal with.
The fifth chapter covers relational databases, and notes that there is a lack of abstraction in databases, so avoiding breakage is much harder, relying on the use of conventions in the database, rather than the use of e.g. javadoc @deprecated tags.
The sixth chapter covers API refactorings, and considers the consequences of adding or removing various features, e.g. constructors, methods, keywords like final. This part of the book is probably the most valuable as it clearly states the possibilities and implications for such activities as introducing a new method in an abstract class and whether it will require recompilation or if potentially erroneous behaviour can result without a compile time error. Here a strategy of using javadoc tags that indicate future and past changes to the code (e.g. method signatures) are advocated to help clients moving to newer versions of the API.
The final chapter gives an example of using the authors' commerical Sotograph tool to visualise architecture and dependencies, followed by a brief conclusion.
I was disappointed by this book. While its brevity is in its favour (you could read it in a day or two), I found little in the book that couldn't be extrapolated directly from smaller scale refactoring. Obviously the authors have a much harder time finding concrete refactorings to apply to software architecture, when such higher level architecture is manifested differently in different programming languages, but the book lacks sufficient practical tips that can be taken away and applied to your own designs.
Also, the book's prose is rather leaden. While it is no weaker than many other stodgily-written IT books out there, compared to Martin Fowler's more deft styling, the discussion here lacks sparkle. Of course, this may be due to being translated from Germany. Nonetheless the writing does not excite.
While Martin Fowler's Refactoring remains a must-read, Refactoring in Large Software Projects is not, and I would be hard-pressed to recommend it over books that touch on related issues, such as Joshua Kerievsky's Refactoring to Patterns, Michael Feathers' Working Effectively With Legacy Code and Eric Evans' Domain Driven Design.
|
|
|