Dynamic Types Ease Refactoring

This page should be deleted as it contains technically incorrect information. Years later it is being proven that with environments like EclipseIde and IntellijIdea 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

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 UnitTests 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? -- AnonymousDonor

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 HandHelds.) 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 UnitTests 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 [BrokenLink] -- BradCox

Is it possible this page is out of date? I've moved from CeePlusPlus to JavaLanguage to PythonLanguage 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 in EclipseIde and others make me able to do refactorings I would never attempt in either CeePlusPlus or PythonLanguage. StaticTyping 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 RenameClasses, methods, and variable names with absolute confidence that the system will not be affected. I can also perform relatively safe MoveMethods 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:
 class Something{
	void aMethod(){}

class Someone{ void aMethod(){} }

class Person{ void aMethod(){} }

{ 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 strict typing

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 :)


View edit of April 10, 2008 or FindPage with title or text search