This week, DZone continues a series of pattern-related Refcardz with Refactoring Patterns, written by Kevin Rutherford, who is also the author of the book Refactoring in Ruby . This card provides an introduction to refactoring, as well as detailed descriptions of various refactoring patterns and a list of useful tools for refactoring various coding languages. Kevin took a few minutes to answer some questions related to his own experiences as a developer, as well as a few expert insights into the problems and practices of effective refactoring.
DZone: Hey Kevin! Thanks for authoring DZone's latest Refcard on Refactoring. Tell us a little bit about your expertise with this subject.
Kevin Rutherford: I've been developing software since 1975, and I guess I have always
been interested in code quality, and in the process of creating and maintaining high quality software. Even back in the Eighties when I worked on high security extensions to the Unix kernel, we found that refactoring was an essential part of keeping our code clean and maintainable. Of course the term "refactoring" hadn't been invented then, and we had no textbook recipes or pattern names for what we did, but in hindsight it was definitely refactoring, and it definitely kept that project alive.
DZone: What have you been working on lately?
Kevin Rutherford: My current list of projects includes a good mix of TDD training, agile
coaching and Ruby/Rails development. Currently my time is split roughly equally between those three types of client.
DZone: How would you describe this card in one sentence?
Kevin Rutherford: It's a quick overview of what refactoring is about in practice, with plenty of practical example code in Java.
DZone: It seems that the decision to refactor rather than start over from scratch may be a tough one. Can you suggest some criteria for deciding between refactoring and rewriting?
Kevin Rutherford: Refactoring is "usually" preferable, because the huge amount of tacit and implicit knowledge buried in the current codebase makes starting afresh a high risk option. I would rewrite if I had to switch to a new language, framework or technology, but in most other cases I try to refactor. Better yet, I try to avoid that hellish future by keeping the code clean now. Little and often is the best approach to refactoring.
DZone: In what situations is it hardest for developers to refactor code, and what is your general solution for those situations?
Kevin Rutherford: Refactoring is hardest when test coverage is low, or when each fragment of code is closely coupled to many others, or when knowledge of external technologies has infiltrated throughout the heart of the codebase. The first priority for getting out of these situations is good coverage by a suite of fast tests, so that's where I always begin. It then always transpires that, in order to create those tests, I have to hide external technologies behind suitable abstractions, and generally decouple the various functions and responsibilities of the
code. In general, code is only safe to refactor when it has good, fast test coverage; and that test coverage can only be achieved in well-designed code consisting of many small loosely-coupled pieces.