Builder vs. Large arg-list constructor

Today I was browsing one of our module’s code. I wasn’t looking for anything in particular, I just wanted to familiarize myself with that part of the system. However, I found something strange; the code was full of object constructions like:

private MyObject myObject = new MyObject(null, null, "", "", importantData, importantData2);

You might say, yes, this class does way too many things if it takes this many arguments. Believe it or not, it actually made sense to keep those data together. The real problem was passing around null and dummy values across the system. And the situation was even worse in case of unit tests.

Let’s see a toy example – a.k.a. code that’s not confidential. We consider the class:

import java.util.Date;

public class User {

	private String userName;
	private String password;
	private String nickName;
	private Date lastOnline;
	private Address address;
	private Balance balance;

	public User(String userName, String password, String nickName,
			Date lastOnline, Address address, Balance balance) {
		this.userName = userName;
		this.password = password;
		this.nickName = nickName;
		this.lastOnline = lastOnline;
		this.address = address;
		this.balance = balance;
	}
}

For the sake of the example, let’s suppose we have object constructions like:

User user = new User("tamasgyorfi", "lotsOfAsterisks", "", null, null, null);

User anotherUser = new User("", "", "chaster", new Date(), null, null);

Well, this is 100% functional, but not that clean. Null values and empty strings make these lines sort of “noisy”. How do we make this cleaner? I think in such situations it is worth to give Builder Design Pattern a try, as it makes object construction more straightforward.

This is how I usually do it, in six easy steps: I

  1. create a new class and name it UserBuilder (I like to add the word Builder so others know what they’re facing)
  2. copy all the fields of the object under construction into the builder
  3. (as far as I know) Eclipse is not able to generate the methods I need, so I have it generate all the setters for the fields
  4. with find/replace I replace all the words “set” with “with”. Also replace the return types from void to UserBuilder
  5. have all the methods return this
  6. create a method named “build”. It does the actual construction and returns the object constructed.

After step 6, we have something like this:

import java.util.Date;

public class UserBuilder {

	private String userName;
	private String password;
	private String nickName;
	private Date lastOnline;
	private Address address;
	private Balance balance;

	public UserBuilder withUserName(String userName) {
		this.userName = userName;
		return this;
	}

	public UserBuilder withPassword(String password) {
		this.password = password;
		return this;
	}

	public UserBuilder withNickName(String nickName) {
		this.nickName = nickName;
		return this;
	}

	public UserBuilder withLastOnline(Date lastOnline) {
		this.lastOnline = lastOnline;
		return this;
	}

	public UserBuilder withAddress(Address address) {
		this.address = address;
		return this;
	}

	public UserBuilder withBalance(Balance balance) {
		this.balance = balance;
		return this;
	}

	public User build() {
		return new User(userName, password, nickName, lastOnline, address,
				balance);
	}

}

So we can replace the object constructions mentioned above with these calls:

UserBuilder builder = new UserBuilder();
User user = builder.withUserName("tamasgyorfi")
				.withPassword("lotsOfSterisks")
				.build();

and similarly:

UserBuilder builder = new UserBuilder();
User anotherUser = builder.withLastOnline(new Date())
				.withNickName("chaster")
				.build();

Cleaner, more straightforward, don’t care things are left out and only relevant arguments are mentioned. And last but not least object construction is moved to one place and it’s not spread across multiple classes.

Note: the ideas above are only valid when your objects are not required to be immutable.

Advertisements

Author: tamasgyorfi

Senior software engineer, certified enterprise architect and certified Scrum master. Feel free to connect on Twitter: @tamasgyorfi

3 thoughts on “Builder vs. Large arg-list constructor”

  1. Hi Tamás!

    Just one short note.
    If you try to avoid constructors with lot of parameters (in our project CheckStyle only allows maximum 3 parameters), it is better to create a constructor with one parameter, which is the builder.

    E.g.:
    public User(UserBuilder builder)

    and assign fields from the builder

    this.userName=builder.userName…etc.

    Of course in this case the builder class should be an inner class.
    And the constructor can be protected, to prevent “users” to instantiate the class without the builder.

    For me, it is clearer than the long parameter lists.

    1. But still, in this case I was facing, it was a kind of good idea not to further break the class into several. Also, it wouldn’t have been a good idea, as these classes are the “heart” of the system and such refactoring had had a pretty large impact on the whole development. This is a more lightweight process.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s