Real programmers don't use refactoring tools

10 August 2007

You know, it's funny. I can well remember the day I saw my first syntax-highlighted code in an IDE. It looked a little weird compared to the flat Notepad look of yester-editors, but, from that point on, non- syntax-highlighted code just became harder to read. It was as if we had been shown the z-axis from having lived in Flatland for so long.

And then came code completion lists. You'd be typing along and if you suddenly became stuck trying to remember a member name, you could wait half a second or so and a list would pop up showing the identifiers you could type in at that particular spot. And again, you were shown another dimension to your code, and there was a split from the past.

And now I see comments like this: "I have to laugh when I see what these tools do. Any coder worth his salt will be instinctively writing code as good as if not better than this tool produces." In case you hadn't guessed, the writer was talking about refactoring tools. In particular, the fake Yorkshireman macho-ness ("When I were a lad, we were lucky to 'ave _fastcall") that infuses the prose might have indicated to you that he was a C++ programmer, and you'd have been right.

This just seems nutty to me and it's not because I work for a company that puts out a refactoring tool. Yes, we all know what refactorings are, the great geek god Martin Fowler wrote a best-selling eponymous book on them. And we all know the names of the most popular ones: Extract Method, Inline Temp, Extract Interface, Move Method, Rename Identifier, and so on. Their names have become a mantra almost, a paean to the new agilism. But, surely -- he says in a baffled voice -- having an automated tool is better than doing them by hand? Aren't refactoring tools just another small step on the way to better visualization of our code and of writing it better and faster? What am I missing that this comment writer implicitly understands, or, rather, vice versa.

The writer of this comment also seems to imply that Code, Once Written, Is Never Changed. It must have been the eleventh commandment, but God ran out of ink when printing it on the stone tablet. But we all know from our own experience, without recourse to statistics, that most code is changed. No matter how good we are, how much we're worth our salt, no matter what language we use, we introduce bugs when we write code. It may be we change it immediately ("Duh, that should be a less than, not a greater than") or it may be later, after testing. And, sure, when we modify our code, or we modify someone else's (because we are lucky indeed if the only code we ever work on is our own), we make use of refactorings as we make fixes.

Think of it like this. Since code will get changed (there's a bug; the requirements change; you prefer to code in an organic fashion as if you were playing with Play-Doh), why not take advantage of a tool that helps you do it? Certainly you can do it all by hand and have members of the opposite sex swoon as they watch you manipulate the code with the keyboard, but to be honest who gives a damn.

I think of the way I write code. I'm an experimentalist developer: someone who develops with TDD (Test-Driven Development). Despite years of programming, I always approach a programming task as a blank sheet of paper. Since I do TDD my blank sheet of paper always starts off with something I'd like to be true (my first test). And then I write the code that satisfies the test, and then I write something else I'd like to be true (another test), and I write more code that makes it so. And so on so forth.

During this continual piecemeal advance towards software of value, my code is completely malleable. Just because I wrote it one way for one test, doesn't mean that it's going to stay that way for ever. I refactor ad nauseam and utterly rely on my refactoring tool to do that.

The refactorings I use most of all are these:

1. Rename Identifier. This one is the most important refactorings in my ever so humble opinion (it's my blog so what I say goes!). When I'm coding, I never seem to get the names of things right the first time. Indeed, I've given up trying to, since it just interrupts the flow of getting an algorithm down. And the names of things are perhaps the most important thing about our code. We can't do anything about the syntax of our language, but, by gum, we can about our identifiers. Name them badly and we obfuscate our code quickly. We've all heard the (apocryphal?) stories about programmers coming across some code where the previous programmer in an effort to be funny used names of flowers or mountains to name local variables.

Compilers don't give a fig about what you name your identifiers. It's your human audience that does, and you can guarantee you'll have one: the hapless maintenance programmer that follows in your footsteps, which, sometimes, is you. You are writing for your human reader first, and your compiler second. Beware if you think it's the other way round, because you'll appear on The Daily WTF. I've learned that the real name for an identifier only becomes obvious once you use it. Sometimes if you find it hard to name an identifier it indicates that your code is not expressing the problem domain properly. So, being able to rename an identifier, without worrying about search-and- replace destruction, is a boon beyond compare.

2. Extract Method. I'm an advocate of small, low- cyclomatic-complexity methods, and ones that have a single responsibility. Ditto for classes, by the way. But constructing a set of interacting methods as a complete thought exercise and getting them all down in source code is a talent that has always eluded me. Call me a stream-of-consciousness programmer by all means, but that generally means slamming it all down and then sorting out the mess afterwards. This is where Extract Method come into its own. Hey, that code over there is essentially the same as this over here, let's extract it into a common method that can be called (reused!) from both locations.

And an automated Extract Method is great: it works out the parameters, constructs the right method signature, inserts calling code at the location where the code was extracted, and in less time it takes to think about the possibility. Toss in a few Rename Identifier refactorings and your code becomes more readable and simpler to understand.

Mind you, me, I can't wait for a tool that will find duplicate code for me. Oooh, at that point the combination may topple Rename Identifier from the top of the list.

3. Create Method Stub. This isn't really a refactoring per se (it makes temporarily non-compilable code into compilable code), but it's so handy for TDD enthusiasts. You're writing a test that defines how you'd like something to read and to work and you find you've used a method name that doesn't exist yet. Hit the refactoring key, and boom, the tool adds a stub method to the right class. Invaluable.

4. Decompose Parameter. This one is rapidly moving up the list ever since I started playing with an early beta version of it from Refactor! Pro. The set up for understanding why this is so good is a little long-winded, but the payoff has all the more impact for it.

When we use a framework like the .NET Framework we find ourselves writing a lot of event handler code so that we can get called back from the framework when something happens. Oftentimes, we'll get a nice handy object passed in as part of the call containing property values we can use in our handler code. The unfortunate thing is these event handlers tend not to be reusable, because the caller has to construct a new handy object to pass in some values. All in all a pain. Especially so when, in general, we are given a particularly rich or heavy object and we only use a couple of its properties. Far better to extract out the specific code into another method, pass in the property values (and not the rich, heavy object), and reuse this new method, including calling it from our event handler.

Enter Decompose Parameter: it works out what's actually being used inside the method's implementation and constructs a method that has those properties as parameters. It then patches up the calling code and you're done. So, instead of a non-reusable event handler that needs an EventArgs but just uses the EventArgs' Graphics property, and hence that requires an EventArgs object to be set up before calling, you get a method that expects a Graphics object instead, and can be used from other painting methods, for example.

5. Move Type to File. One of Refactor! Pro's invaluable refactorings and every time we demo it, people in the audience "get it" immediately. The way we write code these days is to have one class per source file, the latter named after the former. Makes it easy to find the code for classes, and great for when you have multiple programmers working on the same team. But writing code in that way is a pain in the neck. You want a new class, but have to stop what you're doing in order to add a new file to the project, name it accordingly, switch to it, add the new class, switch back to where you were, etc. It's a complete drag to productivity. For the past couple of years, I just continue writing code to build a class model in the same one source file. When I'm ready to extract the classes, I just invoke this refactoring on one class after the other. Boom, boom, boom. Much easier.

6. Extract Interface. Another great refactoring. You've written a class believing it to be the only one you'll need, and, wham, you discover another exemplar that's slightly different. I much prefer interface inheritance to implementation inheritance, and so I'd be doing an Extract Interface so quick it would make your head spin. Mock me, baby.

7. Inline Temp. A quick simple refactoring, nevertheless very useful. It changes code that declares a temporary variable, sets it, and then uses the variable in an expression. This refactoring just gets rid of the temporary variable and moves the initialization into the expression. Sometimes this can make the code a little clearer. Sometimes it won't and you'll need the opposite refactoring; Introduce Temporary Variable. I do tend to use both as I polish code.

8. Use String.Format. Another refactoring that audiences at demos instinctively "get" and that I use all the time. Face it, writing a String.Format call is great for localization efforts, but it's just a real pain to write. It's much easier to write an expression that consists of a bunch of string concatenations, but unfortunately that's hopeless from a localization viewpoint. So, do the easy thing and let the refactoring tool do the tedious work. I love just writing a string concatenation expression, getting it exactly the way I want it, and then convert it to a String.Format call as if I'd done it that way all along.

I'll stop there. My intent here is not to list out all the refactorings I use, only those I use most of all. In doing so, I wanted to indicate why I think a refactoring tool is deserving of being in your coding environment.

Sure, the refactorings I've listed can all be done by hand. Indeed if I were stern and hard-core I'd say do them by hand a couple of times so that you get a real feeling for what each refactoring means and how it works. And I'd laugh my evil taking-over-the-world laugh while you did so. Afterwards you'd just use the automated tool and be thankful that you can save time.

Because in the end, we're not all great programmers who write code correctly in the first pass. We're all programmers writing code to enhance/fix/extend existing code (and even green field projects turn into a marathon of altering code). We're all maintenance programmers to a smaller or larger extent. We're all programmers who have to live with other people's code, and recognize that our code after a few months could be someone else's. And because we're all that and more we deserve the best coding tools we can get. And that includes automated refactoring tools.

21 comment(s)
Terri Rademan

Julian, nice and useful post.  Thanks!

10 August, 2007
Kevin White

When I first heard refactoring, I said "what do I need that for", but now I get it and it saves a great deal of time.

11 August, 2007
Kevin McFarlane

Julian, thanks for being inspired by my email. :-) Of the refactorings you list I think rename, extract method and string.format are the ones I use most often. Next after that would be Create Method Stub.

11 August, 2007

Following on from my post on automated refactoring tools , I was going to talk a bit about how modern

13 August, 2007
Mário Marinato

Great post, Julian.  You did an excellent job.

I just don't agree with its title:  it doesn't fit the text.

When I started reading I thought you'd say that refactoring tools are made for those who don't know how to program correctly, and rely on software wizards to do their job, but long before the end of the text I realised you were talking about how good those tools can be when you know what you're doing.

I'd suggest it to be called "How Real Programmers Use Refactoring Tools".

Brazilian cheers.

14 August, 2007
Julian Bucknall (DevExpress)


The title was a play on words of a well-known book called "Real Men Don't Eat Quiche", so it was meant sarcastically, a joke.

Unfortunately, the allusion would have been lost on non-English speakers, so I should have put it in quotes to help out.

Glad you liked the blog post, though.

Cheers, Julian

14 August, 2007
Mário Marinato

Oh, now I got it.

Well, in fact, I still don't get it, but now I understood why I didn't get it.  Got it?  :o)

Jokes apart, that's the problem with humour:  sometimes it doesn't translate.  Anyway, thanks for the explanation.  I'll try to grab a copy of that book.

Again, congratulations for the post.  I'll surely save it and forward it to my friends.  Plus, you've got a new feed subscriber.

Cheers, Mario

14 August, 2007

Real programmers WRITE refactoring tools.

15 August, 2007
Tony Morris

The only people on this planet who support so-called "Refactoring" are those who only know how to use the poorest of programming languages (strict, imperative, with poor type systems).

This is a fact supported by a huge amount of evidence. Indeed, I *know* this about you, simply by reading your post; it is a successful scientific prediction, isn't it? Can you find a counter-example? (Hint: no). This is an invariable trait with 100% prediction success. Think about this fact some more.

Google for "Refunctoring". Now, discuss in a more informed manner.

18 August, 2007
Matt S Trout

Hm. I think the real point of most people complaining about this sort of stuff is a lot of programmers don't like using -dictated- refactoring tools.

I refactor in an automated fashion a lot, but I do it with :%s in vi and find ... | perl -pi -e '...' - if my code's too complex for that to be possible, I've written in wrong in the first place.

Then again, I don't use syntax highlighting either, since I find my mental parser for code structure actually works better for me and having colour at points where the highlighter config decides is right is, no matter what the config, not always exactly what transitions I want to highlight and just makes it harder for me to read the code.

If you have the right mindset and the right practice, while a dedicated refactoring automation system might be better the effort to learn and remember the means of using said system to do the work isn't worth it compared to using your existing tooling knowledge to achieve the same ends.

The most important thing though is to make those sorts of refactors at all - how you achieve that should be however is most comfortable to you and really a fairly secondary consideration.

18 August, 2007

Real programmers write in binary machine code.

19 August, 2007

Just a pity tools like Visual Studio lack some of the good ones, like `Move Type to Own File.`

But, in keeping with Mark's comment, real programmers DO write refactoring tools, and you can too; except for `Move Type to Own File`, I've done the hard work for you. The code can be found here:

Nice post btw.


19 August, 2007

hehe - and then use that tool to assist in its own maintenance...

19 August, 2007

Refactoring would come naturally in lisp-like programming languages, besides the changing whitespace and how the code is represented in files, all these points can be done with lisp macros.

I myself am playing with lush( found it easier to use so far.

Of course, having to do it with c++ and such may be a fact of life, i am not really experienced, so i am not critizing that.

19 August, 2007
Tom Copeland

> I can't wait for a tool that will find duplicate code for me

Right here!

19 August, 2007
Terence Lewis

There is a java tool called "pmd" which includes a code duplication analyzer. We run it on a CruiseControl.Net build server and it outputs a list of code duplications. I haven't figured out how to tell it to ignore AssemblyInfo.cs files yet, but in general its pretty useful.

19 August, 2007

If you think you need a refactoring tool ... its time to learn how to use editor... oh! your not using emacs... bzt you loose.

19 August, 2007

Great post! I am always confused by refactoring tools. Some friends of mine have sworn by them for Java and C#, but I honestly have never seen the need.

I think part of the reason they are so helpful with languages such as Java/C# is b/c they are languages written with an IDE in mind. As such, they assume that long variable names, huge class libraries, syntax, etc. is all relevant inside an IDE, not a simple text editor. I think this is a bad thing IMHO, but as it is the case these languages are popular, I see now how refactoring tools can make the elegance in the languages rise to the surface.

I personally use Python and XSLT primarily. Python never really seems to need a refactoring tool, but this is primarily b/c of the dynamic nature of the language and the conventions available that make it less advantageous. XSLT on the other hand is verbose and is much nicer to code with a tool like Oxygen.

22 August, 2007

Anyone who doesn't like refactoring tools have never experienced the pain of renaming a variable/method/class by hand!

I guess that shouldn't leave many people, but IMO even the most basic of the base refactorings that is Rename Identifier is extremely useful, especially considering the importance of a good naming convention in one's code.

Sure, you can search and replace each find at a time manually then recompile, but refactoring is SO much more efficient and secure in that case!

31 August, 2007
Tales from the SharpSide

A Quarter of Resharper - The Good and the Bad

12 September, 2007
Scott’s Blog » Refactoring

Pingback from  Scott’s Blog » Refactoring

31 October, 2007

Please login or register to post comments.