Question

I want to write bean-friendly classes. I have observed a tendency (mostly with beans) to move required parameters to setters from the constructor (and use an init() method when done setting up the initial state).

This method concerns me because I want my classes to be usable without a bean infrastructure, just as Java objects. As I imagine I'd have to check for the proper state of the object in every method assert style.

Quick demo for the above:

class A {
    public int x;
    public int y;
    private int sum;

    private boolean initialized = false;

    public void init() {
        sum = x + y;
        initialized = true;
    }

    private void initCheck() {
        if (!initialized) {
            throw new IllegalStateException("Uninitialized object.");
        }
    }

    public int getXMulSum() {
        initCheck();
        return x * sum;
    }

    public int getYMulSum() {
        initCheck();
        return y * sum;
    }

}

Is there a better practice?

Was it helpful?

Solution

Given that you don't want to use a framework...

If a class is not fit for use until it has been initialised, I would prefer using constructors. Don't be swayed by blogs and books. Constructors are there for this purpose. Using constructors also removes any requirement to synchronize your code.

One reason I can see for not using constructors, is if there is a lot of initialisation code and perhaps dependencies external to the class. If too much logic resides in a constructor, then it can make your application brittle and difficult to recover from Exceptions in the constructor. In this case you have the option of using a Factory class that will handle the instantiation and initialisation of the bean. This way, the calling code only ever receives a bean that is ready and fit for use.

A good pattern to use is the Builder pattern where you have a long list of constructor arguments.

"I have observed a tendency (mostly with beans) to move required parameters to setters from the constructor"

The main reason for this testability. If you can test a feature of the bean without having to initialise "expensive" dependencies, than not having them in the constructor is of benefit. Having said that, I would also argue that if this is an issue, you probably have too much functionality in your bean and you'd be better off breaking it up. As suggested by the Single responsibility principle.

OTHER TIPS

The setters are more general than constructor arguments because they allow you to handle circular dependencies.

If you don't have circular dependencies, I'd recommend staying with constructor arguments, exacly for the purpose of enforsing the dependencies.

However, if at all possible, do not put any logic into constructor. As Brad said, it makes the application brittle. The entire Spring environment may not be available during constructor.

Try to design in a way that allows the constructor to simply remember the references for later use in the real methids. Avoid init() method if you can.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top