General musings on programming languages, and Java.

Saturday, May 15, 2010

Refactor: Lazy Initialisation to Eager

A field is being initialised when used, rather than when the object is created.

Extract the initialisation into a separate method that returns the value to store in the field, move the assignment to the field declaration, and inline any private use of the getter.

class Person {
String address;
public String getAddress() {
if (address == null) {
address = "1, The Crescent\n";
address += "Codeville";
}
return address;
}
}
view raw Before.java hosted with ❤ by GitHub

becomes

class Person {
final String address = makeAddress();
public String getAddress() {
return address;
}
static String makeAddress() {
String result = "1, The Crescent\n";
result += "Codeville";
return result;
}
}
view raw After.java hosted with ❤ by GitHub

Motivation

The lazy initialisation is no longer necessary, and harms readability. Additionally, incorrect lazy initialisation can cause problems for concurrent programs.

Mechanics

Where the field is assigned, redeclare a variable shadowing the original field. Rename that variable including its uses, and at the end of the block assign the new variable to the field:

class Person {
String address;
public String getAddress() {
if (address == null) {
String result = "1, The Crescent\n";
result += "Codeville";
address = result;
}
return address;
}
}
view raw Stage1.java hosted with ❤ by GitHub

Extract a method for the operations on the new variable. This should be static, at least during the refactor, to prevent accidental operations on other fields. Other fields' values should be passed in explicitly as parameters. This helps to prevent initialisation-order problems (where y gets initialised before x, but while initialising y, we read x and get a big fat null).

class Person {
String address;
public String getAddress() {
if (address == null) {
address = makeAddress();
}
return address;
}
static String makeAddress() {
String result = "1, The Crescent\n";
result += "Codeville";
return result;
}
}
view raw Stage2.java hosted with ❤ by GitHub

Get rid of the == null check, and make the field final:

class Person {
final String address = makeAddress();
public String getAddress() {
return address;
}
static String makeAddress() {
String result = "1, The Crescent\n";
result += "Codeville";
return result;
}
}
view raw After.java hosted with ❤ by GitHub

No comments:

Blog Archive

About Me

A salsa dancing, DJing programmer from Manchester, England.