General rule for constructors

P

pek

Hello, I've been reading lately Effective Java and Josh Bloch suggests
more than once to avoid using the default public constructors in order
to solve particular problems. More specifically, Item 1 says "Consider
static factory methods instead of constructors" or Item 2 "Consider a
builder when faced with many constructors" etc etc..

While all these paradigms are great (I was stunned when reading the
Builder pattern) I do feel that his general advice for constructors is
thinking like method visibility (start from private and build up to
public):

First try to see if all other are relevant to your problem and then,
as a final solution, create a public constructor.

Is this the way I should be thinking? Is creating a public constructor
the least desired way of constructing an object? Or are these
solutions good only for the problems they specifically solve?

Not that I'm against it. On the contrary, his solutions blow my mind
away (obviously, I'm not the guy you would call an advanced
programmer).

Thank you,
Panagiotis
 
D

Danger_Duck

Hello, I've been reading lately Effective Java and Josh Bloch suggests
more than once to avoid using the default public constructors in order
to solve particular problems. More specifically, Item 1 says "Consider
static factory methods instead of constructors" or Item 2 "Consider a
builder when faced with many constructors" etc etc..

While all these paradigms are great (I was stunned when reading the
Builder pattern) I do feel that his general advice for constructors is
thinking like method visibility (start from private and build up to
public):

First try to see if all other are relevant to your problem and then,
as a final solution, create a public constructor.

Is this the way I should be thinking? Is creating a public constructor
the least desired way of constructing an object? Or are these
solutions good only for the problems they specifically solve?

Not that I'm against it. On the contrary, his solutions blow my mind
away (obviously, I'm not the guy you would call an advanced
programmer).

Thank you,
Panagiotis

What are you trying to do?
 
A

Andrea Francia

pek said:
Nothing in particular. Just asking what is the best way of thinking
when it comes to constructors..

Josh Bloch hints are fine.

Only keep in minds that JavaBeans needs at least a public constructor
with no parameters. This apply only for JavaBeans.
 
D

Daniel Pitts

pek said:
Hello, I've been reading lately Effective Java and Josh Bloch suggests
more than once to avoid using the default public constructors in order
to solve particular problems. More specifically, Item 1 says "Consider
static factory methods instead of constructors" or Item 2 "Consider a
builder when faced with many constructors" etc etc..

While all these paradigms are great (I was stunned when reading the
Builder pattern) I do feel that his general advice for constructors is
thinking like method visibility (start from private and build up to
public):

First try to see if all other are relevant to your problem and then,
as a final solution, create a public constructor.

Is this the way I should be thinking? Is creating a public constructor
the least desired way of constructing an object? Or are these
solutions good only for the problems they specifically solve?

Not that I'm against it. On the contrary, his solutions blow my mind
away (obviously, I'm not the guy you would call an advanced
programmer).

Thank you,
Panagiotis

So, the best advice that I can give you on this subject is borrowed from
a book (I believe Effective C++):

"Make your classes easy to use correctly, and difficult to use incorrectly."

You should consider that rule when deciding on whether you want to use
constructor versus some sort of factory (be it a builder, configurable
factory, static factory method, or something else).

The other important consideration is in the future when you create a
sub-class, or a replacement implementation, will it be easy for users of
your current "instantiation approach" to benefit from your enhancements
(whether it Just Happens, or is a simple change in one place)

And remember Rule #1: Every rule has an exception. Except this one. :)
 
M

Mark Space

Daniel said:
So, the best advice that I can give you on this subject is borrowed from
a book (I believe Effective C++):

"Make your classes easy to use correctly, and difficult to use
incorrectly."

Also, once you think you have correctly outlined how you class should
work, check out some Design Patterns and see if they do something
markedly different. There are patterns for code too, not just design.
Best ways to implement something, and all that.

I think your original statement is good as a general rule. You should
make everything private by default, and then see what you absolutely
have to make public. Don't forget about things like Facades and
Proxies, which can help you hide the real object that does the work.

However, there will also be some specific patterns for what you are
doing, and also some anti-patterns too. Try to find the most specific
ones and apply those. Too much generalization isn't good either.

Time and familiarity will help you find the best patterns quickly. I'm
definitely still learning here too. And mis-designed code that is
nevertheless designed clearly and with forethought shouldn't be that
hard to refactor if you later decide the use of a particular pattern
wasn't the best. "Build one to throw away."
 
A

Arne Vajhøj

pek said:
Hello, I've been reading lately Effective Java and Josh Bloch suggests
more than once to avoid using the default public constructors in order
to solve particular problems. More specifically, Item 1 says "Consider
static factory methods instead of constructors" or Item 2 "Consider a
builder when faced with many constructors" etc etc..

While all these paradigms are great (I was stunned when reading the
Builder pattern) I do feel that his general advice for constructors is
thinking like method visibility (start from private and build up to
public):

First try to see if all other are relevant to your problem and then,
as a final solution, create a public constructor.

Is this the way I should be thinking? Is creating a public constructor
the least desired way of constructing an object? Or are these
solutions good only for the problems they specifically solve?

Not that I'm against it. On the contrary, his solutions blow my mind
away (obviously, I'm not the guy you would call an advanced
programmer).

Note that consider != always.

There are some classes where using a constructor ties a lot
of your code to an implementation that you may want to
change.

JAXP W3C DOM Document is a good example of an alternative
approach and why it is beneficial.

You could argue that Spring is fundamentally based on the
concept.

So consider it and and chose it when it makes sense.

Arne
 
A

Arne Vajhøj

Andrea said:
Only keep in minds that JavaBeans needs at least a public constructor
with no parameters. This apply only for JavaBeans.

It is also sometimes needed with serialization and externalization.

Arne
 
S

softwarepearls_com

I'm a big fan of JB and his Effective Java.. but look at the JDK, and
work out the ratio of public constructors to factory methods. Public
constructors are in an overwhelming majority.. so clearly most people
are perfectly happy with constructors which, yes, hardcode the
implementation type in your logic. Even Bloch's Collections API uses
mostly the constructors approach.

Last but not least, I would argue strongly that software needs to be
thought of as fluid. With modern refactoring tools, we can quickly
make the kinds of changes to whole codebases which just a few years
ago would have been major headaches. JB's best advice is "If in doubt,
leave it out." So given that your static factories are a bit more
complex than plain constructors, I'd say leave them out (initially).
 
D

Daniel Pitts

Arne said:
It is also sometimes needed with serialization and externalization.
Sometimes, but only if you are doing custom work. Standard
serialization will bypass the object initialization phase completely.
No constructor, no default field values (other than the minumum
null/false/0), etc.
 
A

Arne Vajhøj

Daniel said:
Sometimes, but only if you are doing custom work. Standard
serialization will bypass the object initialization phase completely. No
constructor, no default field values (other than the minumum
null/false/0), etc.

If I remember correctly then Externalizable always requires the no arg
constructor and Serializable requires no arg constructors for the stuff
inside the class that are not Serializable.

Arne
 
A

Arne Vajhøj

softwarepearls_com said:
I'm a big fan of JB and his Effective Java.. but look at the JDK, and
work out the ratio of public constructors to factory methods. Public
constructors are in an overwhelming majority.. so clearly most people
are perfectly happy with constructors which, yes, hardcode the
implementation type in your logic. Even Bloch's Collections API uses
mostly the constructors approach.

It is only a small part of classes where one will want to be
able to replace the implementation.

Nobody wants to use a factory class for everything. Think Spring - you
want to dynamically load the critical classes not every class.
Last but not least, I would argue strongly that software needs to be
thought of as fluid. With modern refactoring tools, we can quickly
make the kinds of changes to whole codebases which just a few years
ago would have been major headaches.

I disagree.

Changing lots of code to use a specific implementation is a
bad practice even if it is somewhat automated.

Noone will prefer:

Connection con = new MySqlConnection(constr);

over:

Connection con = DriverManager.getConnection(conurl);

just because you have a fancy tool that can change MySqlConnection
to OracleConnection in the entire application.

Arne
 
J

jolz

Serializable requires no arg constructors for the stuff
inside the class that are not Serializable.

Rather outside the class. For example:

class A {}
class B implements Serializable {
A a = new A();
}

will fail during seralization even though A has a default constructor. But:

class A {}
class B extends A implements Serializable {}

will be ok because not serializable A has a default constructor. Without
it exception would be thrown during deserialization.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top