This page should be deleted as it contains technically incorrect information. Years later it is being proven that with environments like EclipseIde
that statically typed environments perform a much better job at automating refactoring than Smalltalk environments ever did. "Having to wait an hour" or "having to find all the instances of references to that class" are non-problems, the IDE does it for you in literally no time.
If anybody thinks there still are technical arguments to defend the thesis of this page, let him speak, else I am going to delete this page and replace it with the technically accurate information. -- CostinCozianu
You could retain a historical note of it though.
"Refactoring Smalltalk and Ruby is trivial compared to (say) Java. Things just move around. There's no need to jump through hoops to satisfy the compiler." -- DavidThomasOnTheBenefitsOfDynamicTyping
- With dynamically typed languages, the compiler doesn't have to check to see if you broke anything, so you never have the "edit one class, recompile them all" experience. Having to wait an hour to see the result of a minor refactoring is discouraging, to say the least. This can all be overcome in static languages with careful dependency management, of course.
- To rename a class in a language with ManifestTyping, you must change: all the references to the class, plus all the references to instances of the class. To do the same in a language with DynamicTyping, or a language that can do TypeInference, you have to change all the references to the class, but none of the references to instances.
See also: RefactoringWithCeePlusPlus
Both of these points are strawmen. To the first point, consider that for a very popular Smalltalk and Java virtual machine, written in Smalltalk, the UnitTest
s take at least 12 hours to run. The average turn-around to determine if integration broke something was one day. To the second point, search and replace is very fast and easy. Moreover, one rarely changes the name of a class. Integration problems are primarily functional changes (hence the unit tests), and secondarily interface changes (which static typing solves). They are very rarely symbol table collisions. If you can't operate a search and replace function, you have greater problems than programming language theoretics. -- SunirShah
The unit tests ran too long. Fix that. Doesn't relate to refactoring at all.
- Easy to say in your straw shoes. You didn't see the unit tests. Not much to do to speed them up. They were testing class libraries, a compiler and VM (with JIT) in two languages on umpteen platforms.
Do the math. There are more edits to do when you change typed code: there are more occurrences of class names, more occurrences of interface names, and more occurrences of variable names.
And tools make a difference. Search and replace in a nest of files isn't as easy or as accurate as a browser, which for example makes LISP or Smalltalk easier to refactor than Ruby, and sometimes makes refactoring C++ or Java in an IDE easier than without.
My own experience spans file-based and IDE-based typed code (which I liked because, especially in Pascal, the types found certain errors), and Smalltalk, LISP, and Ruby "untyped". I'm sure it was a combination of ingredients, but the latter were all easier to change than the former. It's hard for me to understand how anyone's actual experience
could be different. Perhaps it would be useful to post some examples showing that there's no more typing to do in C++ than in Smalltalk?? -- RonJeffries
You use [keyboard?] typing as a metric? You are joking?
There's an important difference between "easier" and "much more difficult." Of course static typing makes it harder to change code. That's one of its purposes. But it's not terribly difficult. That's why the complaints are strawmen. Don't drop to the ice at the tiniest touch, eh. -- SunirShah
consider that for a very popular Smalltalk and Java virtual machine, written in Smalltalk, the UnitTests take at least 12 hours to run.
12 hours seem incredibly long. How much unit tests do you have? Providing 12hrs ~= 40000 seconds, and assuming, say, 1/10 second per UT there can be as much as 400000 of them? :) 1/10s seems as good time for UNIT test (not acceptance test). -- PavelPerikov
With a suite that big, you have to build
it first. And the "it" is really many dozens of "it." (Think HandHeld
s.) It took a few hours to build every configuration on a compile farm. Then you have to run the tests on each configuration. ConfigurationManagement
has to done with the UnitTest
s too, y'know. ;) -- ss
I wrote a whole rant on this very topic. See "The Problem" in the left column of http://virtualschool.edu/wap
] -- BradCox
Is it possible this page is out of date? I've moved from CeePlusPlus
as my language of choice but I have to say refactoring in Java is an order of magnitude easier than in CeePlusPlus
and probably twice as easy as in Python. We all know CeePlusPlus
is a mess, but Java has a clean enough syntax that automated ReFactoring
and others make me able to do refactorings I would never attempt in either CeePlusPlus
specifically helps here because EclipseIde
can do static analysis to determine whether a specific method invocation should be refactored or not. In a dynamically typed language, no such analysis is possible. In Java, I constantly RenameClass
es, methods, and variable names with absolute confidence that the system will not be affected. I can also perform relatively safe MoveMethod
s and pull up field/methods. In CeePlusPlus
I rarely do more than ExtractMethod
due to the huge overhead involved in updating headers and other class files. In PythonLanguage
, I find myself doing more refactorings than in CeePlusPlus
but far less than in JavaLanguage
due to the uncertainty involved in making such changes. -- BrianRobinson
I've begun to believe that refactoring in Java with EclipseIde is easier than refactoring in SmalltalkLanguage due to the tool's ability to learn more about the structure of the code because of the ManifestTyping.
Tell me, in a loosely typed language, how do you automatically rename a polymorphically-called method when all implementations don't derive from the base class? Catch the obvious ones and hope for the best? :)
In Smalltalk, I hit Rename Method, type in the new name, and then run the tests.
That's what I said. :)
Seriously though, are you renaming every method with the same name? Excuse the java accent but consider:
getPerson().aMethod(); //for whatever reason, this will be a Someone or a Person, never a Something
getThing().aMethod(); //and this will never be a Person or Someone
Now, automatically rename Something.aMethod() to payForOrder(), and Someone.aMethod() to sayHello().
Baring analysis of what objects end up where, I don't see how a loosely typed language can automatically make the distinction necessary to handle this case without a base class of some variety (or do you always use a baseclass for such things?) The strictly typed languages can guarantee, baring reflection, that the code will be correct after the rename: there's no need to run the tests (although I like to anyway)... the semantics haven't changed.
ps. I'm not saying that I like
Ah, I see. Yes, in that case I'd ask for a list of all the implementors of aMethod, and manually choose which ones I want to rename. And then run the tests. :)
True true. Unless the implementor of aMethod stored his knowledge in the code... in the form of the interface he was required to write by the compiler. So the computer can do the work for us. (But we still run the tests).
The idea of course being that the type information is useful to the computer figure out things that we can determine from context or colleagues. Nearly ViolentAgreement
happening here :)