Ah... the sweet sound of refactoring...
One of the programming projects I both love and dread is refactoring. I dread it because some of the code I have to refactor is amazingly old, dense, uncommented, undocumented and really hairy. But it's also the most satisfying feeling in the world to take code like that and turn it into something much better.
For the past few weeks, most of my work life has consisted of refactoring in some way, shape, or form. I have one major refactoring project that I am working on, as well as some smaller "clean up" jobs. As I get burnt out with the one task, I can easily switch to the other and feel like I'm making major head way. It's a very nice symbiosis, if you ask me.
I have a few different "tricks" I use when refactoring, mostly just letting the compiler do the hard work for me. For instance, if I want to see whether a particular class property is no longer being used, I can delete it, compile and see if anything breaks. If everything continues to compile, then my refactoring is done! If something does break, my next task is to undo the deletion, and set the scope to private. Compile again -- did anything break? Yes? Set it to Protected and try again. You get the picture -- it's basically a way to clean up some nasty encapsulation issues, or code cruft. I use these same tricks whether in REALbasic, or in C++ -- they're a general tactic.
Search and replace is another great refactoring tool, but one you have to be somewhat careful of. For instance, we had a class in our hierarchy called ContainerPane, but over the years, its functionality was gradually moved to other classes in the same hierarchy. Eventually, it left us with a class that had nothing more than a Constructor, Destructor and no data members! Basically, it wasn't pulling its weight. So it was time for the class to go. However, this class had been around since the dawn of time, and so it had its furry little fingers up and down the class hierarchy. So I started doing a search and replace scheme. First, I took the entire class out of the project since it was no longer required. Then I did a search for ContainerPane and replaced instances of it with the superclass (SubPane). Had I simply done a "replace everything" scheme, I would have missed a method called IsContainerPane as it would have simply been renamed to IsSubPane (of which there was already a call with that name, on SubPane). So while find and replace can be a very quick refactoring tool, you have to have enough of a gut feeling for the safety of it and keep a very keen eye out for unintended consequences when using it.
The biggest problem I run into when doing refactoring is unintentional breakage of virtual method call chains. The trouble with refactoring the parameter list for a virtual method is the fact that you have to be certain to hit all calls in the virtual method chain, or else things like Super.SomeVirtualMethod may continue to compile, but *skip* a class in the hierarchy accidentally! I would love to see a refactoring tool built into the REALbasic IDE to alleviate this issue. Since all instance methods in REALbasic are virtual, it shouldn't be too terribly difficult to apply a datatype change across the entire hierarchy's call chain. I think the hardest part would be coming up with reasonable UI for it! However, it's a much harder nut to crack in C++ since methods linkage is determined on a case-by-case basis.
What refactoring patterns and tricks do you like to use? What pitfalls would you suggest others watch out for?
