Managing constructors with many parameters in Java

Java

Java Problem Overview


In some of our projects, there's an class hierarchy that adds more parameters as it goes down the chain. At the bottom, some of the classes can have up to 30 parameters, 28 of which are just being passed into the super constructor.

I'll acknowledge that using automated DI through something like Guice would be nice, but because of some technical reasons, these specific projects are constrained to Java.

A convention of organizing the arguments alphabetically by type doesn't work because if a type is refactored (the Circle you were passing in for argument 2 is now a Shape) it can suddenly be out of order.

This question might be to specific and fraught with "If that's your problem, you're doing it wrong at a design level" criticisms, but I'm just looking for any viewpoints.

Java Solutions


Solution 1 - Java

The Builder Design Pattern might help. Consider the following example

public class StudentBuilder
{
    private String _name;
    private int _age = 14;      // this has a default
    private String _motto = ""; // most students don't have one
    
    public StudentBuilder() { }
    
    public Student buildStudent()
    {
        return new Student(_name, _age, _motto);
    }
    
    public StudentBuilder name(String _name)
    {
        this._name = _name;
        return this;
    }
    
    public StudentBuilder age(int _age)
    {
        this._age = _age;
        return this;
    }
    
    public StudentBuilder motto(String _motto)
    {
        this._motto = _motto;
        return this;
    }
}

This lets us write code like

Student s1 = new StudentBuilder().name("Eli").buildStudent();
Student s2 = new StudentBuilder()
                 .name("Spicoli")
                 .age(16)
                 .motto("Aloha, Mr Hand")
                 .buildStudent();

If we leave off a required field (presumably name is required) then we can have the Student constructor throw an exception. And it lets us have default/optional arguments without needing to keep track of any kind of argument order, since any order of those calls will work equally well.

Solution 2 - Java

Can you encapsulate related parameters inside an object?

e.g., if parameters are like


MyClass(String house, String street, String town, String postcode, String country, int foo, double bar) {
super(String house, String street, String town, String postcode, String country);
this.foo = foo;
this.bar = bar;


then you could instead have:


MyClass(Address homeAddress, int foo, double bar) {
super(homeAddress);
this.foo = foo;
this.bar = bar;
}


Solution 3 - Java

What you probably want to do is have a Builder class. Then you would do something like this:

MyObject obj = new MyObjectBuilder().setXxx(myXxx)
                                    .setYyy(myYyy)
                                    .setZzz(myZzz)
                                    // ... etc.
                                    .build();

See page 8 and following of this Josh Bloch presentation (PDF), or this review of Effective Java

Solution 4 - Java

Well, using the builder pattern might be one solution.

But once you come to 20 to 30 parameters, I would guess that there is a high relationship between the parameters. So (as suggested) wrapping them into logically sane data-objects probably makes the most sense. This way the data object can already check the validity of constraints between the parameters.

For all of my projects in the past, once I came to the point to have too many parameters (and that was 8 not 28!) I was able to sanitize the code by creating a better datamodel.

Solution 5 - Java

The best solution is not having too much parameters in the constructor. Only parameters really needed in constructor, are params that are need to correctly initialize the object. You can have constructors with multiple parameters, but also have a constructor with only the minimum parameters. The additional constructors call this simple constructor and after that setters to set the other params. This way you can avoid the chain-problem with more and more params, but also have some convenience-constructors.

Solution 6 - Java

As you are constrained to Java 1.4, if you want DI then Spring would be a very decent option. DI is only helpful in places where the constructor parameters are services or something that does not vary during runtime.

If you have all of those different constructors due to the fact that you want variable options on how to construct an object, you should seriously consider using the Builder pattern.

Solution 7 - Java

I can really recommend using Immutables or POJOBuilder when using the builder pattern.

Solution 8 - Java

Refactoring to reduce the number of parameters and depth of you inheritance hierarchy is pretty much all I can think of because, nothing is really going to help keep 20-something parameters straight. You're just going to have to every single call while looking at the documentation.

One thing you could do, is to group some logically grouped parameters into their own higher level object, but that has it's own problems.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSteve ArmstrongView Question on Stackoverflow
Solution 1 - JavaEli CourtwrightView Answer on Stackoverflow
Solution 2 - JavaJeeBeeView Answer on Stackoverflow
Solution 3 - JavaMichael MyersView Answer on Stackoverflow
Solution 4 - JavaThomas MorgnerView Answer on Stackoverflow
Solution 5 - JavaMnementhView Answer on Stackoverflow
Solution 6 - JavaGuðmundur BjarniView Answer on Stackoverflow
Solution 7 - JavaTomas BjerreView Answer on Stackoverflow
Solution 8 - JavaAaron MaenpaaView Answer on Stackoverflow