factory objects (idle thoughts)

S

Stefan Ram

I read this in the world wide web:

»Having dismissed constructors and static factories, it
seems we need to define a factory class whose instances
will support an interface that includes a method that
constructs the desired objects. How will you create the
factory object? By calling a constructor? Or by defining
a meta-factory? After how many meta-meta-meta- ..
meta-factories do you give up and call a constructor?«

http://gbracha.blogspot.com/2007/06/constructors-considered-harmful.html

One answer that came to my mind:

An application may use a constructor /once/ to get its first
object, thereafter it uses only factory methods of this
object and other objects to get all other objects.

(This might have nothing to do with practical Java
programming, I know.)

It reminds me of Amiga programming, where, in 1985,
programmers learned that there is /one/ fixed address, i.e,
the address 4. So an application would go to address 4 to
find the base address of the system library object (it was
not called »object«, then) and all other objects it would
retrieve directly or indirectly from this object.
 
A

Arne Vajhøj

Stefan said:
I read this in the world wide web:

»Having dismissed constructors and static factories, it
seems we need to define a factory class whose instances
will support an interface that includes a method that
constructs the desired objects. How will you create the
factory object? By calling a constructor? Or by defining
a meta-factory? After how many meta-meta-meta- ..
meta-factories do you give up and call a constructor?«

http://gbracha.blogspot.com/2007/06/constructors-considered-harmful.html

One answer that came to my mind:

An application may use a constructor /once/ to get its first
object, thereafter it uses only factory methods of this
object and other objects to get all other objects.

(This might have nothing to do with practical Java
programming, I know.)

It reminds me of Amiga programming, where, in 1985,
programmers learned that there is /one/ fixed address, i.e,
the address 4. So an application would go to address 4 to
find the base address of the system library object (it was
not called »object«, then) and all other objects it would
retrieve directly or indirectly from this object.

GoF somewhat suggested a singleton factory.

Arne
 
T

Tom Anderson

I read this in the world wide web:

?Having dismissed constructors and static factories, it
seems we need to define a factory class whose instances
will support an interface that includes a method that
constructs the desired objects. How will you create the
factory object? By calling a constructor? Or by defining
a meta-factory? After how many meta-meta-meta- ..
meta-factories do you give up and call a constructor??

http://gbracha.blogspot.com/2007/06/constructors-considered-harmful.html

One answer that came to my mind:

An application may use a constructor /once/ to get its first
object, thereafter it uses only factory methods of this
object and other objects to get all other objects.

(This might have nothing to do with practical Java
programming, I know.)

It reminds me of Amiga programming, where, in 1985,
programmers learned that there is /one/ fixed address, i.e,
the address 4. So an application would go to address 4 to
find the base address of the system library object (it was
not called ?object?, then) and all other objects it would
retrieve directly or indirectly from this object.

You are spot on in identifying this as a bootstrap problem - that it can't
be factories all the way down, there has to be a concrete act of creation
at some point.

However, the solution isn't necessarily a real constructor call. In fact,
i think it can't be - if you construct a concrete root factory, then
you're implicitly fixing the behaviour of the root factory's factory
methods, and so the factory methods of any factories created by those,
etc.

Rather, i think what you want to do is root the construction tree in some
magic that allows the class of the root factory to be chosen at runtime.
This could be something like:

RootFactory rfac;
if (isRunningOnDesktop()) rfac = new GUIRootFactory();
else if (isRunningInBank()) rfac = new FinancialRootFactory();
else rfac = new DefaultRootFactory();

But you might be better off doing:

String rootFactoryClassName = AppConfig.getRootFactoryClassName();
Class<T extends RootFactory> rootFactoryClass = Class.forName(rootFactoryClassName).asSubclass(RootFactory.class);
RootFactory rfac = rootFactoryClass.newInstance();

Where the classname comes from a configuration file, a system property, or
whatever. That lets you control the type of factory as a matter of runtime
configuration, rather than it being hardcoded.

And once you're doing this, you're basically rolling your own dependency
injection framework, and you should probably be using Spring or some such.

tom
 
M

Mike Schilling

Stefan said:
It reminds me of Amiga programming, where, in 1985,
programmers learned that there is /one/ fixed address, i.e,
the address 4. So an application would go to address 4 to
find the base address of the system library object (it was
not called »object«, then) and all other objects it would
retrieve directly or indirectly from this object.

Or the way disks are organized in VMS. There a block called the home
block that points to the root directory and the other important data
structures (like the bitmap of free blocks). It's at a fixed location
[1], while everything else can be almost anywhere.

1. In later versions, somewhere in a list of fixed locations, so that
one strategically located bad block doesn't make the disk unusable.
 
M

Mike Schilling

Tom said:
However, the solution isn't necessarily a real constructor call. In
fact, i think it can't be - if you construct a concrete root
factory, then
you're implicitly fixing the behaviour of the root factory's factory
methods, and so the factory methods of any factories created by
those,
etc.

The root factory's behavior could be heavily influenced by
configuration parameters, the environment, the hardware resources
available, etc. The argument you're msking is analogous to saying
that a computer's behavior isn't flexible because it always searches
for the disk boot block at the same location.
 
A

Arne Vajhøj

Lew said:
Arne said:
GoF somewhat suggested a singleton factory.

All of the above is predicated on "[h]aving dismissed constructors", a
fragile premise.

True.

Avoid constructors is one of those rules that has a good point in some
cases, but end up with a ridiculous result when applied consistently
to everything.

Arne
 
T

Tom Anderson

The root factory's behavior could be heavily influenced by configuration
parameters, the environment, the hardware resources available, etc.
The argument you're msking is analogous to saying that a computer's
behavior isn't flexible because it always searches for the disk boot
block at the same location.

If the disk can't be written to (in the way that classes can't be altered
at runtime, absent a debugger), then i think that analogy is moderately
sound. Yes, the root factory could have complex behaviour (as i said in my
post, in fact), but ultimately it is limited to the options available when
it was written. If you get the root factory by dynamic loading, then
it's an extension point which admits infinite possibilities.

Of course, not all problems need infinite possibilities to solve, and a
hardwired flexible root factory may be a better choice than a dynamically
loaded one, particularly if you don't have a dependency injection
framework to make that easy for you.

tom
 
S

Sreenivas

Ah, I love to see All stalwarts of this group discussing something.
Only Roedy Green is missing, though. :)
 
D

Daniel Pitts

Stefan said:
I read this in the world wide web:

»Having dismissed constructors and static factories, it
seems we need to define a factory class whose instances
will support an interface that includes a method that
constructs the desired objects. How will you create the
factory object? By calling a constructor? Or by defining
a meta-factory? After how many meta-meta-meta- ..
meta-factories do you give up and call a constructor?«
The point I take from that paragraph is actually subtle. Abandoning
constructors completely leads to infinite regress. A bad situation to
be in :)

One simple solution, which should be obvious, is to allow the Factory
classes to use Constructors (or Static Factories).

The best solution is use Factories only where they improve the design,
and use Constructors only where they make sense. In other words, use a
little bit of common sense in applying best practices.

When you use IoC (such as in the Spring Framework), it becomes a bit
easier to avoid explicitly using a Constructor, as the framework itself
does that bit of work for you.
 
M

markspace

Stefan said:
I read this in the world wide web:

»Having dismissed constructors and static factories, it
seems we need to define a factory class whose instances
will support an interface that includes a method that
constructs the desired objects. How will you create the
factory object? By calling a constructor? Or by defining
a meta-factory? After how many meta-meta-meta- ..
meta-factories do you give up and call a constructor?«


Your question seems to be "how do you start?" One can imagine a large
and complicated framework, but maybe something simple is the best place
to start. Basics like use of interfaces and design basics like
Inversion of Control are always reasonable places to start.

I say the same thing as Tom -- a class name in a config file is the
ultimate form of Inversion of Control (specifically Dependency
Injection) and is something to at least consider. So how do you start that?

Assuming your application has more than one property -- more than one
config string -- it seems reasonable that we can start like this:

public interface Application {
void startUp( java.util.Properties props );
}

Now you have a mechanism to call Class#forName, using the property
object. You can make your factory by fetching a name out of this
Properties object and calling forName(). You can also configure any
other part of the application by defining a key-value pair in the
Properties.

But how does this method start? What about the code that runs before
startUp()? There's no need to invent further complexities at this
point, in my opinion. As someone said in response to another question,
"just code it."



public class Bootstrap
{
private Bootstrap() {}

public static void main( String... args )
throws IOException, ClassNotFoundException,
InstantiationException, IllegalAccessException
{

// load properties file

Reader propReader = new BufferedReader( new InputStreamReader(
Bootstrap.class.getResourceAsStream(
"/application.properties" ), "UTF-8" ) );
Properties props = new Properties();
props.load( propReader );


// create and start application

String appName = props.getProperty( "main.application" );
Application app = (Application) (Bootstrap.class.forName(
appName ).newInstance());
app.startUp( props );
}
}


This isn't nice to test (and I didn't test it), but once tested, there
should be no need to change it. We load a properties file called
"application.properties" from the root of the Jar file or classpath,
then uses it to find the application to run. We also pass in the
properties themselves so the application can use them to configure itself.

There are problems here. We really should do something about those
exceptions that the method throws (the proverbial exercise for the
reader ;) ). And it really needs some user friendly error trapping,
just in case -- we should really wrap that call to startUp() in a
try-catch, in case the application exits with an Exception.

But here we have a super simple application framework that can be used
to inject all behaviors into a new application (including the class name
of the application itself) and is also fairly easy to test due to its
relative simplicity.

There's no need to make a "factories all the way down" framework. Just
start at the obvious place, and if it works, great. If it falls short,
refactor to make the simplest thing that will work.
 
A

Arne Vajhøj

Daniel said:
The point I take from that paragraph is actually subtle. Abandoning
constructors completely leads to infinite regress. A bad situation to
be in :)

One simple solution, which should be obvious, is to allow the Factory
classes to use Constructors (or Static Factories).

The best solution is use Factories only where they improve the design,
and use Constructors only where they make sense. In other words, use a
little bit of common sense in applying best practices.

When you use IoC (such as in the Spring Framework), it becomes a bit
easier to avoid explicitly using a Constructor, as the framework itself
does that bit of work for you.

Spring is fine.

But I would not recommend using Spring for every object creation either.

Arne
 
D

Daniel Pitts

Arne said:
Spring is fine.

But I would not recommend using Spring for every object creation either.

Nor would I recommend Spring of every object creation. Spring and Guice
are great for "wiring up" business object graphs. E.G., nearly static
structures of the running system. However, for active, dynamic,
short-lived objects in your system, using Spring/Guice is at best
difficult, and at worst problematic.

If you have to jump through hoops to do something, you're probably doing
it wrong.

That doesn't mean you can't still use IoC at the dynamic level of your
app, you just need to put it in more explicitly (having and using a
Factory<T> interface, for instance)
 

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

Forum statistics

Threads
473,982
Messages
2,570,190
Members
46,736
Latest member
zacharyharris

Latest Threads

Top