Refactoring tool challenges in a strongly typed language (poster session)
Authors: Christopher Seguin
Venue: Addendum to the 2000 proceedings of the conference on Object-oriented programming, systems, languages, and applications (Addendum) (2000)

This poster examines the challenges of developing a refactoring tool for a weakly typed language such as Smalltalk as opposed to a strongly typed language such as Java. To explore this, we will compare the push up field refactoring in each language. This refactoring was selected because it is relatively simple conceptually, but difficult to implement for Java. In a weakly typed language such as Smalltalk, push up field is simple. The user simply determines that the parent class needs the variable. The refactoring tool moves the field to the parent class. Then the tool searches all the subclasses of the parent class, if the classes have a variable with the same name, the refactoring tool removes the variable from the subclass. The task is complete. For Java, a description of classes and types is necessary. Let's start with a base class A. A has a number of child classes, B, C, D, E, F, and G. Each of B-G has a single instance variable named var. The only difference between the classes is the type of var. B and C both have a variable named var with type X. D has a variable named var with a type Y. E has a variable named var with type W. F has a variable named var with a type of Z. And G has a variable named var with the type int. W, X, Y, and Z are classes. W is the base class, X is a subclass of W, and Y is a subclass of X. Z is unrelated to all of the other classes. Since all subclasses of A have a variable named var, a programmer might suspect that they could reduce the amount of code by moving the variable into the parent class A. Let's move the field named var from class B into class A. Like in Smalltalk, the Java refactoring tool can remove the variable var from B and C, since the var variable in both classes have the same type. The source file for A would get the declaration of type X named var. The source file for A might also gain an import for the type X. Let's postpone the discussion of the scope of the variable var. The refactoring tool can remove var from D since the storage in A is sufficient. However, the impact on the source code depends on whether there is a difference between the interface of X and Y. If there are methods or fields added in Y that are not in X, then by removing the variable var from D, the refactoring tool must be sure to cast var back to a Y in code that refers to var in a way that accesses the differences. For instance, if X and Y have a method m, then in D the invocation var.m() remains unchanged. If Y has a method n and no similar method is present in X or a parent class of X, then D must change the code that looks like var.n(); to ((Y) var).n(); The refactoring tool cannot remove var from E, since a variable of type W can not be stored in a class X. A refactoring tool might change the type of the object in class A to W. The effect of casting var to an X or a Y type would be more widespread. To remove var from F, the refactoring tool would need to change the variable var's type to Object, since Object is the base class for all classes thus would be a common storage type for Ws and Zs. Everywhere that var is used in any source files, it must be cast to the appropriate type, eliminating the benefit of compile time type checking. Removing var from G is even more difficult, since a primitive type such as int does not derive from Object, the refactoring tool must find a way to store var for G. Java provides a series of immutable types that store the primitive types, i.e. java.lang.Integer. To access the variable's value, &ldquo;var&rdquo; would be replaced with &ldquo;var.intValue()&rdquo;. To set var, the tool would create a new instance of the Integer class, and assign it to var. Since multithreaded programming is encouraged, any operation that replaces an atomic action with a series of steps must be considered very carefully. In this instance, the assignment of a value to var is atomic, but now includes the creation of an Integer object followed by an assignment. Object instantiation is not atomic, therefore if might be necessary to wrap the assignment of var in an appropriate synchronized block. Synchronized blocks are computationally very expensive, and should not be used indiscriminately. Therefore, an automated tool should not remove the variable var from G as a result of pushing var from B to A Instead, a refactoring tool might recommend renaming the variable var in G.