Is Automatic Refactoring Possible in Dynamic Languages?
Perhaps I am limited by my experience with dynamic languages (Ruby on Netbeans and Groovy on Eclipse), but it seems to me that the nature of dynamic languages makes it impossible to refactor (renaming methods, classes, pushing-up, pulling-down, etc.) automatically.
Is it possible to refactor AUTOMATICALLY in any dynamic language (with any IDE/tool)? I am especially interested in Ruby, Python and Groovy, and how the refactoring compares to the 100% automatic refactoring available in 开发者_如何学编程all Java IDEs.
Given that automatic refactoring was invented in a dynamic language (Smalltalk), I would have to say "Yes".
In particular, John Brant, Don Roberts and Ralph Johnson developed the Refactoring Browser which is one of the core tools in, for instance, Squeak.
My Google-fu is weak today, but you could try find this paper: Don Roberts, John Brant, and Ralph Johnson, A Refactoring Tool for Smalltalk, "The Theory and Practice of Object Systems", (3) 4, 1997.
Smalltalk does not declare any types. The Refactoring Browser has successfully performed correct refactorings in commercial code since 1995 and is incorporated in nearly all current Smalltalk IDE's. - Don Roberts
Automatic Refactoring was invented in Smalltalk, a highly dynamic language. And it works like a charm ever since.
You can try yourself in a free Smalltalk version (for instance http://pharo-project.org)
In a dynamic language you can also script refactorings yourself or query the system. Simple example to get the number of Test classes:
TestCase allSubclasses size
I have wondered the same thing. I'm not a compiler/interpreter writer, but I think the answer will be that it is impossible to get it perfect. However, you can get it correct in most cases.
First, I'm going to change the name "dynamic" language to "interpreted" language which is what I think of with Ruby, Javascript, etc. Interpreted languages tend to take advantage of run-time capabilities.
For instance, most scripting languages allow the following
-- pseudo-code but you get the idea
eval("echo(a)");
I just "ran" a string! You would have to refactor that string also. And will a be a variable or does this language allow you to print the character a without quotes if there is no variable a?
I want to believe this kind of coding is probably the exception and that you will get good refactoring almost all of the time. Unfortunately it seems that when I look through libraries for scripting languages, they get into such exceptions normally and maybe even base their architecture on them.
Or to up the ante a bit:
def functionThatAssumesInputWillCreateX(input)
eval(input)
echo(x)
def functionWithUnknownParms( ... )
eval(argv[1]);
At least when you refactor Java, and change a variable from int to string, you get errors in all the places that were expecting the int still:
String wasInt;
out = 3 + wasInt;
With interpreted languages you will probably not see this until run-time.
Ditto the points about the Refactoring Browser...it is highly effective in Smalltalk. However, I imagine there are certain types of refactoring that would be impossible without type information (whether obtain by explicit type annotation in the language or through some form of type inferencing in a dynamic language is irrelevant). One example: when renaming a method in Smalltalk, it will rename all implementors and senders of that method, which most often is just fine, but is sometimes undesirable. If you had type information on variables, you could scope the rename to just the implementors in the current class hierarchy and all senders when the message is being sent to a variable declared to be of a type in that hierarchy (however, I could imagine scenarios where even with type declaration, that would break down and produce undesirable results).
精彩评论