DAO design advice

W

Wendy S

When I wrote my data access layer, I followed the J2EE DAO Pattern, and so I
have

public abstract class DAOFactory
{ public abstract AddressDAO getAddressDAO();
public static DAOFactory getDAOFactory()
{ return new UniDataDAOFactory(); }
}
and
public class UniDataDAOFactory extends DAOFactory
{ public AddressDAO getAddressDAO()
{ return new UniDataAddressDAO(); }
}

But it has grown and grown, and I don't want to include all the DAO classes
in every project. (For example, the accounting reports webapp doesn't need
all the DAO classes for the fund raising system.) But it feels wrong to
leave those classes out of the .jar file when the DAOFactory refers to them.

I'm considering removing all of the getWhateverDAO() methods from the
factory, and just doing this:

public abstract Object getDAO( String daoType ) throws DAOException;

Then the caller is responsible for supplying the type of DAO he wants, and
for casting the resulting Object to the correct type. Since I am a
development team of one, I'd like some feedback on this before I make the
change.

So far, the implementation (in UniDataDAOFactory) looks like this. It
expects the caller to supply mp.ContactDAO if they want a
my.package.mp.UniDataContactDAO, thus the substring manipulation.

public Object getDAO( String daoType ) throws DAOException
{
try {
int pos = daoType.lastIndexOf( "." );
if ( pos > 0 ) {
String pkgName = daoType.substring( 0, pos );
String className = daoType.substring( pos + 1 );
String fqn = "my.package.data." + pkgName + ".UniData" +
className;
Class theClass = Class.forName( fqn );
return theClass.newInstance();
} else {
String fqn = "my.package.data.UniData" + daoType;
Class theClass = Class.forName( fqn );
return theClass.newInstance();
} } catch ( Exception ex ) { throw new DAOException( ex ); } }


Does this look reasonable? I realize it opens up the possibility of more
runtime errors, since you can mistype the 'daoType' parameter and the
compiler can't catch it. Is there anything else I should consider?

Thanks for your time,
Wendy S
 
J

John C. Bollinger

Wendy said:
When I wrote my data access layer, I followed the J2EE DAO Pattern, and so I
have

public abstract class DAOFactory
{ public abstract AddressDAO getAddressDAO();
public static DAOFactory getDAOFactory()
{ return new UniDataDAOFactory(); }
}
and
public class UniDataDAOFactory extends DAOFactory
{ public AddressDAO getAddressDAO()
{ return new UniDataAddressDAO(); }
}

But it has grown and grown, and I don't want to include all the DAO classes
in every project. (For example, the accounting reports webapp doesn't need
all the DAO classes for the fund raising system.) But it feels wrong to
leave those classes out of the .jar file when the DAOFactory refers to them.

Do the DAOs sort themselves out reasonably neatly into exclusive (or
mostly exclusive) categories? It sounds like they might. In that case
you could create several more specific DAOFactory implementations, one
for each category. That still leaves open the possibility of an
uber-Factory as a facade for the collection of all the more specific
factories, if you should need something like that.

I'm considering removing all of the getWhateverDAO() methods from the
factory, and just doing this:

public abstract Object getDAO( String daoType ) throws DAOException;

Then the caller is responsible for supplying the type of DAO he wants, and
for casting the resulting Object to the correct type. Since I am a
development team of one, I'd like some feedback on this before I make the
change.

So far, the implementation (in UniDataDAOFactory) looks like this. It
expects the caller to supply mp.ContactDAO if they want a
my.package.mp.UniDataContactDAO, thus the substring manipulation.

public Object getDAO( String daoType ) throws DAOException
{
try {
int pos = daoType.lastIndexOf( "." );
if ( pos > 0 ) {
String pkgName = daoType.substring( 0, pos );
String className = daoType.substring( pos + 1 );
String fqn = "my.package.data." + pkgName + ".UniData" +
className;
Class theClass = Class.forName( fqn );
return theClass.newInstance();
} else {
String fqn = "my.package.data.UniData" + daoType;
Class theClass = Class.forName( fqn );
return theClass.newInstance();
} } catch ( Exception ex ) { throw new DAOException( ex ); } }


Does this look reasonable? I realize it opens up the possibility of more
runtime errors, since you can mistype the 'daoType' parameter and the
compiler can't catch it.

It looks like it could work. As you point out, there is a potential for
it to hide bugs. Such might slip into the production release if they
reside in rarely-exercised parts of the code. Also, if you rely on
normal Java class resolution then automated tools (e.g. Ant) can analyze
the .class files to automatically determine which need to go into which
jars (transitive closure of classes based on their dependencies);
reflective class loading hides the information necessary for that.

Your proposal has the advantage of being brief, but I can't say I really
like it. On the gut feeling level, changes from more object oriented
toward less object oriented generally feel wrong to me. Moreover, it
doesn't really solve the problem you initially posed, which was that you
didn't want to exclude any of your factory's dependencies, but also
didn't want to include classes that you could know in advance would be
unused. Your solution does not remove the factory's dependencies: it
merely hides them. In one sense, you could say that it actually
broadens the scope of its dependencies to everything in your package.
Is there anything else I should consider?

See above.


John Bollinger
(e-mail address removed)
 
W

Wendy S

John C. Bollinger said:
Do the DAOs sort themselves out reasonably neatly into exclusive (or
mostly exclusive) categories?
In that case you could create several more specific DAOFactory implementations, one
for each category.

That will work. For some reason I wanted to avoid having more than one
factory.

Thank you very much for taking the time to look over this.
 

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,774
Messages
2,569,598
Members
45,152
Latest member
LorettaGur
Top