Question

I was reading through testable code that follows LoD, but got all messed up in my head. So please any guidance regarding this piece of code would be appreciated.

public class HouseConfiguration {

    private final int noOfDoors;
    private final int noOfWindows;
    //.... And so on

    public HouseConfiguration(int noOfDoors, int noOfWindows){
        this.noOfDoors = noOfDoors;
        this.noOfWindows = noOfWindows;
        //.....
    }

        //getters for config
}

public class Contractor {

    public House buildHouse(HouseConfiguration houseConfiguration) throws Exception{
        validateHouseConfiguration(houseConfiguration);
        Window[] windows = new Window[houseConfiguration.getNoOfDoors()];
        return new House(windows);
    }

    private void validateHouseConfiguration(HouseConfiguration houseConfiguration) {
        //validation logic
    }
}

public class House {

    private Window[] windows;

    //Now as the parameters increase it becomes a problem to pass so many arguments in constructor
    public House(Window[] windows /*Also other arguments */) {
        this.windows = windows;
    }

}

Now as the arguments of the House constructor increase it would be difficult to manage it using constructor. Lots of dependencies would be getting passed. Is it a correct thing to do? Or is there a better way that this code can be refactored?

EDIT: Referring to the House constructor arguments

Was it helpful?

Solution

...as the arguments of the House constructor increase it would be difficult to manage it using constructor.

Use the Builder pattern (Effective Java item 2):

public class House {

    //these are immutable if you wish
    private final int mNumberOfWindows;
    private final int mNumberOfDoors;

    private House(HouseBuilder builder) {
        mNumberOfWindows = builder.mNumberOfWindows;
        mNumberOfDoors = builder.mNumberOfDoors;
    }

    public static class HouseBuilder {
        private int mNumberOfWindows; //set defaults here, make final and pass in builder constructor if they must be set
        private int mNumberOfDoors;

        public HouseBuilder windows(int numberOfWindows) {
            mNumberOfWindows = numberOfWindows;
            return this;
        }

        public HouseBuilder doors(int numberODoors) {
            mNumberOfDoors = numberODoors;
            return this;
        }

        public House build() {
            return new House(this);
        }
    }

    public int getNumberOfWindows() {
        return mNumberOfWindows;
    }

    public int getNumberOfDoors() {
        return mNumberOfDoors;
    }
}

Usage:

    House.HouseBuilder hb = new House.HouseBuilder();
    hb.doors(4);
    hb.windows(3);
    House h = hb.build();

    House h2 = new House.HouseBuilder().doors(4)
            .windows(3).build();

OTHER TIPS

I was do it in this way (sorry, it is a C#):

public interface IHouseConfiguration
{
    int noOfDoors { get; set; }
    int noOfWindows { get; set; }
    bool IsValid();
}

public class HouseConfiguration : IHouseConfiguration
{
    public HouseConfiguration(int noOfDoors, int noOfWindows)
    {
        this.noOfDoors = noOfDoors;
        this.noOfWindows = noOfWindows;
    }

    public int noOfDoors
    {
        get { return noOfDoors; }
        set { noOfDoors = value; }
    }

    public int noOfWindows
    {
        get { return noOfWindows; }
        set { noOfWindows = value; }
    }

    public bool IsValid()
    {
        //do validate calculus and return value. For a true, i do not sure it is IHouseConfiguration's duty...
        return true;
    }
}

public class Contractor
{
    public House buildHouse(IHouseConfiguration houseConfiguration)
    {
        if (houseConfiguration.IsValid())
        {
            return new House(houseConfiguration);
        }

        return null;
    }
}

public class House
{
    private Window[] windows;

    public House(IHouseConfiguration houseConfig) //Now, all incapsulated in IHouseConfiguration
    {
        Window[] windows = new Window[houseConfig.noOfDoors];
        this.windows = windows;
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top