Constructors don’t get better with age!

The main goal of the article is to make you remember 2 things:

  1. Constructors aren’t like cheese i.e. they don’t get better with age
  2. An “ad litteram” iterative approach on writing constructors is BAD

How bad you wonder? Well… this bad:

new Admin(code,
 name,
 propId,
 locale,
 description,
 service,
 emailAddress1,
 emailAddress2,
 oldEmailAddress,
 generalReports,
 noVat,
 parId,
 junk,
 dateJoining,
 sessionId,
 type,
 typeOther,
 crId,
 keyAccountTypeId,
 crmId,
 virtual,
 acCoConfirmed,
 acRe,
 sanct,
 timestamp,
 passwordExpiryDays,
 concurrentLogins,
 suspensionDays,
 contractVersionId,
 vat,
 version);

Usually when you add a new filed to an existing class, usually domain model classes, you have 2 options:

  • Enhance the existing constructor by adding a parameter. But this will affect all the existing code. Do you really want to brake existing integration?
  • The “Telescopic way”: create a new constructor that has just one more parameter that delegates the initial parameters to the initial constructor. This won’t affect existing integration, but, in time it will lead to very hard to read code – sample above.

Of course, there are patterns to solve this. You may go for the static factory method way, but, again you may end up in a similar situation:

BankAccountFactory.create(
null,
number,
null,
"SWEDEN",
null,
null,
null,
null,
null,
accName,
accResidence,
null,
"EUR",
null,
null,
null);

[/pre]

Don’t worry, there are better patterns. The best I recommend is the Builder pattern presented by Joshua Bloch in Effective Java. More details here: http://www.informit.com/articles/article.aspx?p=1216151&seqNum=2. And it also uses to some extent the Fluent Interface pattern presented by Martin Fowler in this post: http://martinfowler.com/bliki/FluentInterface.html. This pattern is very powerful because it allows you to enforce consistency for your objects. Well … this is not exactly quite true as you can still supply null/invalid values to the constructor. That’s why I’m proposing a lighter alternative by getting rid of the actual Builder which duplicates code a little with the downside of loosing that formal enforced consistency. So the code will look like this:

public class Account {

     private String id;
     private String owner;
     private String accountNumber;
     private Date expiryDate;
     private int level;

     public static Account create() {
         return new Account();
     }

     public Account withId(String theId) {
         this.id = theId;
         return this;
     }

     public Account withOwner(String own) {
         this.owner = own;
         return this;
     }

     public Account withAccountNumber(String an) {
         this.accountNumber = an;
         return this;
     }

     public Account withExpiryDate(Date date) {
         this.expiryDate = date;
         return this;
     }

     public Account withLevel(int lev) {
         this.level = lev;

         return this;
     }

     public String id() {
         return this.id;
     }

     public String owner() {
         return this.owner;
     }

     /*
      * etc
      */

     public static void main(String... args) {
         Account ac = Account.create().withId("20").withAccountNumber("ABCDEF")
                 .withOwner("me").withExpiryDate(new Date()).withLevel(4);
     }

 }

What do you think?

Advertisements

2 Replies to “Constructors don’t get better with age!”

  1. The scenario that you are discussing calls for either dependency injection or Inversion of control. Inversion of Control (IoC) works with constructors, so that is the better solution to solve a problem like this. With Inversion of Control you pass the constructor an object that can build the dependencies for you dynamically based on what dependencies your “registered” with the IoC container beforehand.

    1. That’s not always true. you can use IoC when you bind classes that do stuff, but when you create an entity for example that’s being used as a parameter for a function, you must build the object explicitly with the data you need. IoC is not the way to go in this case.

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