I keep hearing people say they couldn’t possibly use Ruby because it lacks automatic refactoring tools. And although it will eventually have some of them, there’s a class of automated refactorings that are automatable in Java but not in Ruby. This, people say, is a show-stopper.
I wonder.
What exactly is refactoring? I mean, it’s not a word in the dictionary.
Fowler tells us that it’s the art and science of turning smelly code into good code, in small, incremental steps. Provably correct, by construction. Algorithms for giving your code a makeover without breaking it in the process.
He gives us a nice taxonomy. He presents some good techniques, especially geared for Java programmers. Some are things we had already figured out and are habitual, and some of them are new.
Some of these “refactoring” techniques are automatable. And many of them are useful in languages other than Java. It seems Fowler and friends have stumbled on something real, something as big as OOP, almost. Or at least they were the first to market it and package it properly. Either way, we know about it now. Thank you, Fowler and friends!
Refactoring is one of the first programming books I’ve seen that talks about the almost mystical act of writing code. It takes the process, exposes all the insides, revels in it, walks you line by line through oh so many little decisions that affect code quality. These are things most people never talk about. They take them for granted. Most people talk about “architecture”. Refactoring talks about the idioms in the code we write every day. Real now-code, not planned someday-code.
It’s remarkable, really, that nobody talks about this. They leave all the so-called style choices to the programmer. Refactoring rubs our noses in the implications of our line-by-line style choices. Beautiful.
Discovering Refactoring
Refactoring caught my eye in the bookstore one day in 2002, years after it was published. I hadn’t read it because it was published by those UML weenies. I’ve just never been a fan. It has its uses in database modeling (maybe), but I’ve never found it useful in class modeling. And I’ve never cared for the Booch/Jacobsen/etc. crowd’s books.
Refactoring is right there, smack in the middle of that weenie series. Every time I see it, my eyes sweep across the cover without a second glance. You know the old saying!
But one wintery day in 2002, I’m in the bookstore, and I pick it up. No real reason. I’m curious. Don’t know why. Maybe I’d finally heard the word “refactoring” somewhere. What did it mean? It’s not a word in the dictionary.
“Factoring”, sure, that’s a dictionary word. You can factor numbers, or polynomials. Factoring I know. Don’t know why you’d re-do it, though. What’s “re”-factoring?
I open the book. It says local variables are the root of all evil. Perhaps not exactly those words, but it’s the first discussion I stumble across. Local variables!? I plop down in a squashy armchair, outraged, to read more. I want to know if this guy is actually insane, or merely an idiot.
Horror sets in: he’s right. His explanation makes chilling sense. One of my cherished programming practices — caching intermediate values in local variables, as an inline performance optimization — is clearly demonstrated, before my very eyes in the squashy armchair, to be Evil. It explains why I have certain methods in my code base that keep growing and growing, and for reasons I’ve never been quite able to grok, the methods are unsplittable.
These big methods, they’re the Bad Places. The areas of the code base where I loathe to tread. Dark caves that grow more evil every time I visit them. Because add functionality I must, but the locals have threaded their way impenetrably through each function, spiderwebs that catch me and hold me.
The book shows me why they’re unsplittable, then gives me axes to split them. Sharp and precise tools. And the techniques make sense, right then and there. Some even appear to be automatable. Wow.
I move on. Turning pages faster, now. Interested.
The book next tells me: don’t comment my code. Insanity again! But once again, his explanation makes sense. I resolve to stop writing one-line comments, and to start making more descriptive function and parameter names.
I buy the book, take it home, read it over and over. I marvel. It appears to be pure genius. To this day, I still feel that way, although perhaps not so greatly as I did on that day. But the book is a landmark, and it made me a better programmer overnight. How often does that happen?
Sudden embarrassment. How could I not have read this back in 1998? I’m awash with a horrid cold feeling, as if I’ve just learned I’ve been coming to work for years with my pants down around my ankles. Has everyone else at work already read this book? Am I the only one who didn’t know?
I ask around the next day. Casual. Cool. Not tipping my hand. You’ve read Refactoring, right? Nope. Everyone I ask says No. Most haven’t heard of it. Out of 20 developers I survey, only one guy has read it. No surprise there, since he reads everything. His vote? “Yeah, that’s a great book!”
I feel a rush of relief. Most people don’t know about it, then. I’m safe. I can study it, use it, not worry that everyone will know how foolish my code has been. My code had only been bad along a few dimensions. Most of it was well-engineered. I used design patterns, unit testing, source control, all the usual software engineering discipline. It just smelled a little bad, and now I could fix it.
Refactoring Today
Everyone knows about Refactoring nowadays, because IDEs now have all of the automatable refactorings from the book, and a few extras to boot.
But despite its overnight popularity, I doubt most engineers have read Fowler’s book, not even a few chapters of it. I suspect most engineers today don’t realize there are still many refactorings that are not automatable, even in Java. Most of them, even. Although that’s a topic for another day.
Today, I still don’t know exactly why they called it Refactoring. Catchy, I guess. It feels distantly related to factoring, in the math sense. Reorganization? Too broad. Refactoring seems fine.
Sometimes a good name is all that lies between a great idea and mass acceptance.
Refactoring today is an entire industry. It’s a banner. It’s the battle cry of Java-IDE lovers everywhere. Refactoring tools are Productivity in a Bottle. You browse a menu of refactorings, choose one, and the earth moves.
Why is automated refactoring so popular in the Java camp, and nowhere near as popular in other languages?
Java people say it’s because only Java allows you to accomplish this level of automation of code transformations.
Reprise
I keep hearing people say they couldn’t possibly use Ruby because it lacks automatic refactoring tools. And although it will eventually have some of them, there’s a class of automated refactorings that are automatable in Java but not in Ruby. This, people say, is a show-stopper.
I wonder.
I read Fowler. I absorbed it. It’s the art and science of taking smelly code and turning it into better code, in small provable steps.
But he taught us something else, didn’t he?
Oh, but you wouldn’t know what that thing is, if you haven’t read his book. Have you? All of it? No skimming? C’mon now. Admit it. You skimmed.
Here’s the deal: to show us the paths from bad code to good, Fowler had to show us bad code. He showed us examples of what it looks like, and explained why it’s bad. He gave us a set of warning indicators and even called them “Code Smells”. More clever marketing? Perhaps. But they’re right on the mark.
How did that code get smelly in the first place?
Well, we optimized prematurely. We stored too many intermediate values, for fear of recomputing them. We didn’t write small functions, for fear of virtual method-call overhead. We made bloated class heirarchies for the imagined benefits of reuse. We made huge parameter lists to avoid allocating a container object. We used null everywhere as a semantic token. We allowed boolean-logic expressions to grow into unreadable thickets. We failed to encapsulate data and data structures with accessor methods. And many more bad things besides.
We were making dozens, hundreds of little mistakes that added up to some pretty smelly code. The book catalogued our mistakes, gave them names, elevated them to First-Class Mistakes.
Then, presumably, we stopped making them? Well, maybe those of us who read the book. Even if we read it late. Better late than never. After reading it, you know what bad code smells like, and you know how it got that way. You’ve learned how to avoid writing it.
At what point did automated refactoring tools become the focus? The book’s original focus was about design, with tools for recovery. Now the focus is all on recovery, and specifically on the automatable subset of recovery techniques.
The implicit assumption here is that bad code just happens, inevitably. Even though we know all about its characteristics, and we know how to spot it instantly. Heck, if you read the book, you know it wasn’t just a catalog of 100-odd specific refactorings. It also presented themes. Once you get the core ideas, you can invent your own refactorings, and identify new code smells.
And now you know better how to write the code correctly the first time around.
Oh, you disagree? Because code is a living thing, and requirements change constantly? Yes. Code needs to change. But Refactoring isn’t the whole story on code change; it’s a relatively small part. There’s data modeling, and architecture, and design patterns, all the high-level astronautics. And of course the custom code-pattern transformations you apply almost daily that aren’t general enough to give first-class names. Changing any of these things requires techniques that I assure you do not have entries in the Refactoring menu of your IDE.
Refactoring is zoomed waaay in. It’s focused on how you personally wrote this or that class or method, down at the level where you were making choices about local variables, control-flow constructs, and other micro-design decisions.
You now know how to avoid doing the wrong things, at that level.
Well — you know if you read the book, that is. Without skimming. And also, I suppose, only if you were already experienced enough for the book to stab at you like a blade, mocking you for not noticing every one of these things yourself, so that you will remember its lessons in your bones for the rest of your days.
Did Refactoring make us lazy? Maybe so. Especially if we skimmed it, or just read the tools-half without reading the explanation-half. Then maybe we think the whole story is about recovery from code that inevitably goes sour. And even if you read the book, maybe those siren-song automatic refactorings have made you forget what the book was really about. Namely, fixing your code and then never again writing so amateurishly.
Is this the whole story? No. Do I sometimes still need to refactor my code? Yes. Are there subtleties I’m punting on for now? Yes. Refactoring can’t really be discussed in a vacuum; it’s interdependent with other modern development ideas, including “don’t repeat yourself”, “once and only once”, unit testing, and others. I may revisit refactoring again in that context.
Today, though I’m just interested in why Java programmers are saying that the ability to “program” by pushing buttons is so critically important to them that they’re unwilling to consider using another language. Even a language that’s gaining rapid worldwide recognition as a step-function in productivity at least as great as Java was over C++, with almost none of the downsides or friction of similar-looking predecessors like Perl and Python.
I mean, they won’t even consider trying Ruby? Gosh. Pushing buttons must be… wonderful.
I close my eyes, envisioning that kind of power…
Pushbutton Productivity
Ah, those automated refactorings. Such programming power — instant productivity with the click of a button. Programming by Menu Selection. Choose your automated attack, and the very earth moves. Mechanical muscles moving mountains of code. It’s almost as if you’re superhuman. Programming never felt so much like a video game.
It must feel like piloting an earth-mover: a John Deere, a Komatsu, a Caterpillar — one of those huge yellow mechanical dinosaurs with the world’s largest tires, the ones that held us in awe when we were children. The driver pulls a lever, a hill of dirt moves aside. The work of a hundred men in a day, accomplished with the bored flick of a wrist. A lifeless yellow behemoth at your beck and call.
Now that’s productivity. If my job were moving mountains of dirt around, then I agree: I would not possibly be able to work effectively without an earth-mover, some tractors, a dump truck, maybe a crane or a backhoe. My personal tools for refactoring the surface of the earth. You couldn’t pry my fingers from their hundred-ton hulks.
Caterpillar. Such an odd name for a motorized Colossus. Or is it? They named it after a little segmented bug. All the segments look alike, repeating themselves. Each segment has two identical tiny legs. The legs have to move in coordinated waves to propel the bug forward. So much computational processing devoted entirely to crawling around in the mud!
Yes, I see it now. Caterpillars are long, machine-like insects. Earth-movers are huge, insect-like machines. It begins to make sense.
Automated code-refactoring tools work on caterpillar-like code. You have some big set of entities — objects, methods, names, anything patterned. All nearly identical. You have to change them all in a coordinated way, like a caterpillar’s crawl, moving all the legs or lines this way or that.
How did our code get that way to begin with? We wrote it badly. Refactoring to the rescue. Good design may be a lost cause, but we can recover, because we have automated servants to go fix all those little segments for us. They never get tired, and all we have to do is push buttons.
Well then. How could you possibly live without automated refactoring tools? How else could you coordinate the caterpillar-like motions of all Java’s identical tiny legs, its thousands of similar parts?
I’ll tell you how:
Ruby is a butterfly.

Steve, I love your 'opnions', you simply rock! Now I'm heading to amazon! ;)
Refactoring has been on my "to read" list for a while now. Until reading your post, I didn't realize how desperately I needed it. Now, I'm feeling the same guilt as you describe in the beginning of your post about not having read Refactoring until now. Besides being really informative, this post was beautiful. I hope Refactoring reads as well as this post did!
Nice article. Now I've got to go and reread refactoring to see how much I missed the last time.
Great post! I too discovered Refactoring a few years ago and since then have become a big fan. It is nice to see someone else with the same enthusiasm. Along with the book, Martin Fowler's site is a great resource. Check out his blog and articles, he has a lot of good information there:
http://www.martinfowler.com/
This is great. I am in the middle of Fowler's book right now, and I was planning on blogging about it. You beat me to it. It's a good thing, too, because I never could have put it this well.
I felt much the same way reading Refactoring. I learned a lot just by looking at the example code (another book that contains similar gems is Kent Beck's Smalltalk Best Practice Patterns).
But that doesn't mean that the discipline of refactoring existing code isn't useful in itslf. It's actually a cornerstone of agile methods, enabling the evolution of an applications's design. The book isn't a catalog of ready-made solutions to code problems, it's a list of small, safe, program transformations. As an evidence, just look at how many rafactorings are the complete opposite of other refactorings (extract method and inline method are obvious examples).
Refatoring isn't done only when the "requirements change" (though they tend to often enough). In an agile process, one whithout a big design up-front, refactoring is done after adding each new feature, in order to always keep the design in top shape. That's how to dynamically conciliate KISS and sound software architecture.
And one word on automated refactorings. I am personally quite fond of them because they help make the process of coding similar to writing prose, in that it's easy to make changes to code while you are with your hands on the keyboard, so to speak.
A similar thing that I hear all the time from folks who won't try Ruby is that they could never give up the little IDE method name completion menus. This is, of course, another thing that is hard or impossible to do in Ruby.
As engineers we should be looking at these questions from a cost/benefit point of view. Simply saying, "I could never live without..." is not engineering. The question is, do we get enough of a productivity gain with Ruby to offset the loss of push button refactoring and method menus? My money is on the clean, expressive language.
Ugh. There goes more money for books out of my pocket :(
Great article though. I guess this is one book I can't put off reading anymore.
Just added to my wish list. Great article.
With Ruby on Rails, the creator of the framework futher forces the porgrammer to write code that doesn't smell by having them write code in certain places (ie Business Rules in the Model) etc. Futhermore in my day job I develop in VB.NET. VS 2003 doen't have any refactoring tools, but I refactor my code every day. All you need is unit tests, a compiler and "Find and Replace" and you can refactor efficiently...
Hey Steve:
I'm going to preface this by saying that I enjoy your articles. I hope you continue to write more. As a corporate developer, a lot of the stuff you rant about rings a bell.
I'd love to change to language X. The problem is that we have invested lots and lots of money into language J, as have lots and lots of other people who have written lots and lots of libraries that we have found useful. In fact, any new problem domain that we need to tackle usually already has a solution ready for you in problem J. The superior languages (even the ones that have been around for 40+ years) have been staring at the mirror or naval gazing while the inferior languages were out solving problems.
When I bring up your CoolGuy Language X with my managers--who, coincidentally, make the decisions in my company--they say "That sounds nice, and Language X looks really cool, but we made our decision a long time ago." In fact, you'll find that most of the companies out there making real money have taken the same path that my company took. It seems the only way I can be one of the Elite Manbag Carrying CoolGuy Ruby Developers is to create a buzz-word happy startup that replicates the functionality of an already existing client app using web technology (extra 2.0 whuffie if it uses Ajax or RoR).
Aside from language choice, I LOVE my company. We solve fun, hard problems--it just happens that our language of choice is Language J. We may be able to solve them a smidge faster using a different language, but we've been doing Language J so long, that we really don't see Language J when we look at the code anymore--just the particular solution used. And last I checked you can't do embedded development with languages R, P, L and S. There's a huge potential coming up for embedded development. Where are the other languages in this space? Language J is standing on a pile of cellphones just waiting to be knocked off.
Good luck with your crusade--I hope the non-entrenched are listening.
Some of the original work in refactoring was done in smalltalk by Don Roberts. He wrote a refactoring browser there. So, if refactoring can be safely handled in a dynamic language like Smalltalk then there is no reason why it could not also be done in Ruby (if people found a need).
Refactoring is defined as a series of semantic-preserving code transformations. Complex ones are built up from simple refactoring primitives. The ability for a language to support refactoring relies and being able to define a set of primitives that can be guaranteed (under some ideal circumstances) to preserve semantics. While this is possible in Ruby there are significantly many circumstances under which primitive refactoring transformations cannot be guaranteed to preserve semantics (meta-programming is a major cause of this pain - but also a major reason that refactoring isn't so desperately needed).
So while refactoring is useful, Ruby isn't suited to it. I suspect that you could use some automated refactoring - but you would have to either bulk up on metadata to describe your application to the tool or otherwise you will have to write your Ruby code in a certain way so the tool can work with it - but then what would be the point of using Ruby.
BTW "Ruby is a butterfly"? Give me a break! It is my favourite language but I wouldn't say it is that special. It has wide ranging abilities - but your average Java programmer will make a dog's breakfast of it (probably worse than they do to Java) - they'll be crying for a refactoring ide (or their workmates will be) no matter what language they work in.
P.S. The insect you describe is a centipede (or millipede, even). Caterpillar's generally only have "true" legs at the front and some variable (depending on family) "prolegs" along their bodies. Pedantic, I know - but..I just .... can't seem .... to .... stop ..... typing!
You just sold an extra 50 copies of that book. :)
re: the name. Factoring is like 12 = 1x12, 2x6 or 3x4.
Refactoring is like taking that 1x12 page method and turning it into 2x6 page methods, 4x3 page methods, or ideally a half-dozen classes each with a half-dozen 3 line methods.
OK, maybe I'm just a great developer (because I did read Refactoring in 1998 and it stabbed me to the core), but I see the IDE automated refactorings in a completely different light than you. I see them as productivity accelerators that make even more complex "refactorings" possible, because you can so quickly take care of those little, automatable steps in a significant refactoring that might be targeted at addressing the larger issues you enumerated (data modeling, architecture or design patterns). They're not just for lazy "bulldozer" operators that think the only way to live is by pushing mountains of statically typed code around all day by push button.
As an example, just take the act of moving a heavily used public method from one class to another and renaming it in a good sized code base. Without automated refactorings (or types), this results in anywhere from 20 to a few hundred intricate series of editing steps, relying on full text search to ensure you hit all affected code locations. With a good tool that supports move member and rename public member, your editing steps have dropped dramatically. This allows you to focus your attention on higher order problems without losing your train of thought.
When I start programming in dynamically typed languages again, I know I will miss the feeling of being able to cut through all the little editing details of a massive, higher order refactoring as quickly as I can by using keyboard shortcuts in a statically typed IDE. Perhaps this is a reasonable price to pay for all the benefits of switching to Ruby, but I'm unconvinced. Until I am, I'd like to keep my power saw.
Wow, as someone new to programming (and self taught) these little gems of information are very important! Keep them comming... (off to Amazon...)