Reorder parameters
One of the refactorings we're including in C# 2.0 is "reorder parameters." Strangely enough, it doesn't do what you think it might do. Wait... nevermind. It does exactly what you think it might do, it allows you to reorder the parameters in a signature. Any that calls that will then have their arguments reordered appropriately.
This is, of course, something you could do manually (all refactorings are), however it's potentially painful and possibly error prone. It's painful when you reorder parameters on a method that is called in 1000 places. It's potentially error prone in certain cases. Imagine the following:
class C {
void Foo(int i, string s) { ... }
}
If we reorder the parameters of Foo, it's simple to recompile and just fix up everything that breaks. However, what if you have:
class C {
void Foo(int i, int j) { ... }
}
If you reorder that you better make sure that you find all the places that call that and fix them up, otherwise you're going to have a bug. These types of reorderings are especially dangerous because after the reorderings your code continues to compile just fine.
A final example is the one I showed here at Tech-Ed. It's dear to me because it's something that bit me at one point. I started with the following code:
class BinaryNode {
private BinaryNode left;
private object value;
private BinaryNode right;
public BinaryNode(BinaryNode right, object value, BinaryNode left) {
//initialize fields
}
}
Now, at one point I realized that I wanted to reorder the left/right arguments to the constructor. I knew everything would still compile, so I did a find for all instances of "new.*BinaryNode" and fixed them up to call in the right order. However, i still ended up breaking something and it took quite a while to figure out what. Can you guess what it was?
The basic issue was that I had subclassed BinaryNode at one point and forgotten that I had a call to base(...) in the constructor. It was this sort of issue that using the re-order parameters helps you prevent. By using us we make sure that any code that calls the thing you're reordering will be fixed up for you.
If you have more than 5 things calling your constructor/method, do you want to manually fix them all up, ptentially making mistakes along the way? Or would you prefer something that goes ahead and does it all automatically for you. If it's the former, why? What do you prefer about manually modifying code. Are there issues with trust when it comes to modifying code? Do you want to actually see what's getting changed? I know I sometimes do. By going and fixing up every location I get a good feel for the code base. For example, by routinely traversing the code (even though it' painful), I can sometimes spot bugs, or opportunities for refactoring.
Comments
- Anonymous
May 26, 2004
The comment has been removed - Anonymous
May 27, 2004
Paul: One thing to note is that with every single refactoring we provide we give you the option to "Preview" the changes. This gives you a two paned view. The top pane shows you all the files that we're going to modify. Clicking on any file then shows you all the changes we're going to make in that file in a lower pane.
That way you can use our refactoring to safely make all the changes, but you can also review the changes that are going to be made in order to get a feel for the code. Hopefully that will help.
I don't have any ideas about C++ and refactorings. I know there aren't any in the community preview which we just released. Hopefully you can find a C++ blogger to ask. - Anonymous
May 27, 2004
The comment has been removed - Anonymous
May 27, 2004
Bart: Nope. But it's an excellent point. We should probably warn that reordering parameters could cause the order of some operations to change. I don't have the C# spec in ffront of me, but I do believe it specifies an left-to-right ordering in how arguments are evaluated. By reordering them you are necessarily changing the semantics in that regard.
This is similar to rename and reflection. Say you're using reflection to instantiate a type based on a string. If you rename that type then the instantiation will fail. This is because, like it or not, names of things have semantics that matter in the reflection domain.