Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Java

Constructors Don’t Get Better With Age!

4.80/5 (2 votes)
14 Dec 2013CPOL1 min read 6.3K  
Constructors do not 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:

Java
new Admin(code,
 name,
 propId,
 locale,
 description,
 serviceNo,
 emailAddress1,
 emailAddress2,
 rfiEmailAddress,
 generalReports,
 vatNumber,
 partnerId,
 junk,
 dateJoining,
 appSessionId,
 legalType,
 legalTypeOther,
 contractRelationshipId,
 keyAccountTypeId,
 crmId,
 virtualTerminal,
 acquirerCountryConfirmed,
 acquirerUsesRegistration,
 sanction,
 timestamp,
 passwordExpiryDays,
 concurrentLogins,
 nonUseSuspensionDays,
 contractVersionId,
 calculateVAT,
 version);

Usually, when you add a new field 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 break 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:

Java
BankAccountFactory.create(
null,
number,
null,
"SWEDEN",
null,
null,
null,
null,
null,
accountHolderName,
accountHolderResidence,
null,
"EUR",
null,
null,
null);

Don’t worry, there are better patterns. The best I recommend is the Builder pattern presented by Joshua Bloch in Effective Java. More details can be found here. And it also uses to some extent the Fluent Interface pattern presented by Martin Fowler in this post. 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 losing that formal enforced consistency. So the code will look like this:

Java
public class Account {

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

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

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

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

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

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

     public Account level(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._new().id("20").accountNumber("ABCDEF")
                 .owner("me").expiryDate(new Date()).level(4);
     }
 }

What do you think?

Filed under: Best Practices, CodeProject, Design Patterns
Tagged: builder, constructor, design pattern, fluent interface

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)