Constructor that fully initializes the state of the object. A good practice for any class, but especially important for ValueObjects, since ValueObjectsShouldBeImmutable.
Is this another way to say ResourceAllocationIsInitialization / ResourceAcquisitionIsInvocation / ResourceAcquisitionIsInitialization combined with the view that it's bad to do:
MyObject aObject = MyObject(); aObject.setFribbible(20);Shouldn't this say something about instance vars that are identity vs state vs cache?
I don't think it's necessarily bad to call mutators after construction: after all, for many objects it is perfectly sensible to have mutating state. I do think, however, that objects should be in fully initialized after they have been constructor. So it would be bad to do something like:
MyObject aObject = MyObject(); aObject.initialize();Yet, I've seen code like the above. In fact, many objects (e.g. JavaServlets, EnterpriseJavaBeans) don't have the necessary context for performing initialization in their constructor. Therefore, they need two-phase initialization with separate methods. This is arguably a DesignSmell.
Yes; but which principles would you use to fix it, given that they "don't have the necessary context for performing initialization"?
Pass the context directly to constructor. For example the servlet-specification could require that servlets implement one-argument constructor that receives ServletContext?. The problem with this solution is that there's no way to perform compile-time checking for that. Perhaps the approach taken by the servlet-specification is a decent trade-off. Still, for my own classes, I try to perform initialization in the constructor.
Often in Java frameworks like those that implement servlets and EJB containers use reflection to instantiate concrete instances, and call Class.forName().newInstance(), which calls only the default no-arg constructor. After the container has an instance it needs to put the just-created object in the right state or associate it with the appropriate context. Deep within the guts of a factory method this is OK, but the client code (application) should never see an incompletely initialized instance. Alternately, for performance, containers may chose to cache instances rather than letting the old ones get garbage collected and always creating new instances. In this case, having a non-constructor method that allows for an instance to be reverted to some initial or appropriate state means that the cached instances can be treated as new objects.
If the context isn't available when you construct the object, an initialize() method may be the easiest way to proceed. I use setX methods after construction when a class has a large number of configurable parameters, which would make a constructor unwieldy. These are each CodeSmells that suggest places to refactor.
See BuilderPattern, IsValid().