Following are the two approaches:
Pros: I have to put an exact number of types of parameters so if I m
You've missed the biggest pro of having a constructor with loads of parameters: it lets you create immutable types.
The normal way of creating immutable types without huge constructor nastiness is to have a helper type - a builder which maintains the values you'll want in your final object, then builds the immutable object when you're ready.
setters and the default empty constructor
JRL obliquely touched on it, but one reason to consider using setters is to have the object conform to the JavaBean specification. This makes instances amenable to editing via introspection tools and persistence using certain serialization techniques.
There are other strategies here, too. Before trying to figure out how to deal with lots of parameters, I think it is important to re-visit your design and look at whether your class is doing too much. See if you can group some of the parameters together into a new class, and move some behavior into that class.
You might look at the Builder pattern advocated by Joshua Bloch, and described in Effective Java. There's a presentation with the main points at http://developers.sun.com/learning/javaoneonline/2007/pdf/TS-2689.pdf; no doubt you could dig up a better reference.
Basically, you have another class, probably an inner class, which provides methods named after the properties being set, and which return the original builder so you can chain calls. It makes for quite a readable chunk of code.
For example, let's suppose I have a simple Message
with a few properties. The client code constructing this could use a builder to prepare a Message
as follows:
Message message = new Message.Builder()
.sender( new User( ... ) )
.recipient( new User( ... ) )
.subject( "Hello, world!" )
.text( messageText )
.build();
A fragment of Message.Builder
might look similar to the following:
public class Builder {
private User sender = null;
// Other properties
public Builder sender( User sender ) {
this.sender = sender;
return this;
}
// Methods for other properties
public Message build() {
Message message = new Message();
message.setSender( sender );
// Set the other properties
return message;
}
}
Recent academic research (CMU and Microsoft) on API usability suggests that default constructors with setters would be the way to go in terms of usability. This is from "Usability Implications of Requiring Parameters in Objects' Constructors" by Jeff Stylos and Steven Clarke and was presented at the International Conference on Software Engineering:
Abstract: The usability of APIs is increasingly important to programmer productivity. Based on experience with usability studies of specific APIs, techniques were explored for studying the usability of design choices common to many APIs. A comparative study was performed to assess how professional programmers use APIs with required parameters in objects' constructors as opposed to parameterless "default" constructors. It was hypothesized that required parameters would create more usable and self-documenting APIs by guiding programmers toward the correct use of objects and preventing errors. However, in the study, it was found that, contrary to expectations, programmers strongly preferred and were more effective with APIs that did not require constructor parameters. Participants' behavior was analyzed using the cognitive dimensions framework, and revealing that required constructor parameters interfere with common learning strategies, causing undesirable premature commitment.
Who says you can't do both? I'd say mandatory properties go into the constructor, optional ones are handled with setters. BTW, who says you always need one setter per property? If two properties belong together conceptually, why not set them together?
I like the Builder pattern too, but the most important rule is: always use your brain and find the design that best fits the specific problem. There's no one-size-fits-all solution.