DAO but not

Okay, I'll start by saying I'm fairly new to server-side development. As a means of teaching myself a bit, I've figured to write a simple forum system using MVC, based on servlet/jsps.

I've come up with a pretty accurate class diagram for the classes involved. As a simplified example: Message (representing a user posting), Topic (representing essentially a collection of messages), User, etc.

Here's where I'm running into problems -- I was going to go with a basic DAO pattern. A few questions/headaches have come up around this though...

a) Is it reasonable for your DAOs to perform object caching as well? I'm implementing this way because it seems like a logical place to do it... so whenever a DAO assembles an object, it adds it to a hashmap for retrieval by the same key used to load it.

b) This is the part that's killing me-- an example: The Message class has a User who represents the author of that message. It aso has a Signature associated -- the Signature is specific to the author, but the author may choose from among any of their registered Signatures for each message, therefore it's assocated with the Message object.

How do I load these aggregated objects using the DAO pattern? When creating the Message, it's really inefficient to load ALL of the dependent objects (User, Signature, etc) at the same time -- I'd rather not load them until they're needed.

Would it make sense for the Message object itself to know that if its Signature hadn't been loaded, and someone called the get method, it should load it? That's what 'feels' right, but it doesn't quite seem to fit into the standard DAO pattern.

i.e.,

publicclass Message{

... .

public Signature getSignature(){

if (theSignature ==null){

// using UserDAO because signatures are owned by users,

// not by the Message

UserDAO dao = UserDAO.getInstance();

theSignature = dao.getSignature(getUser());

}

return theSignature;

}

...

}

And c) As is hinted at above, I've also broken up the DAOs into logical groups -- for all user-dependent data access, I have UserDAO.For all Message-dependant access, i have MessageDAO, etc.I've implemented these as singletons, as I'm not seeing the advantage of a factory in this case (one DB...) -- thoughts on that are welcome too...

As if that weren't enough, I have another question around DAO, the 'business' objects and aggregate data.As an example, a Topic represents a collection of messages. The view will iterate through the messages in a topic and display title, post date, author name, and last reply info.Under the covers, I have the Topic as havintg a collection of Messages.But again, I'm stuck in the same situation as earlier -- the Message is expensive to load. I can do a query that gets me the aggregate data I need to display much more efficiently -- but that doesn't fit anywhere into my model... perhaps an AggregateMessage, used only within Topic?But then the view is driving business logic..

I've spent the better part of a day digging around for answers to this type of problem, and have been able to find very little. Any thoughts/ideas/suggestions are appreciated.

[3702 byte] By [Grinning_Foola] at [2007-10-2 5:30:26]
# 1

> Okay, I'll start by saying I'm fairly new to

> server-side development. As a means of teaching

> myself a bit, I've figured to write a simple forum

> system using MVC, based on servlet/jsps.

>

Great!

> I've come up with a pretty accurate class diagram for

> the classes involved. As a simplified example:

> Message (representing a user posting), Topic

> (representing essentially a collection of messages),

> User, etc.

>

Excellent start!

> Here's where I'm running into problems -- I was going

> to go with a basic DAO pattern. A few

> questions/headaches have come up around this

> though...

>

> a) Is it reasonable for your DAOs to perform object

> caching as well? I'm implementing this way because

> it seems like a logical place to do it... so

> whenever a DAO assembles an object, it adds it to a

> hashmap for retrieval by the same key used to load

> it.

>

Caching is a separate issue. There are dozens of issues to tackle when designing a proper cache. I would recommend using a third-party or open source existing solution. Or use a cache-pluggable O/R mapper like Hibernate.

> b) This is the part that's killing me-- an example:

> The Message class has a User who represents the

> e author of that message. It aso has a Signature

> associated -- the Signature is specific to the

> author, but the author may choose from among any of

> their registered Signatures for each message,

> therefore it's assocated with the Message object.

>

These are referred to as graphs of objects in memory. And yes, they can get messy, especially if there are bi-directionaly (or worse) circular relationships. You generally just 'start' at a given part of the graph, say User or Message or whatever is the top-level object in the graph you are trying to build. Once that is decided, it is straightforward how you will fetch other objects.

> How do I load these aggregated objects using the DAO

> pattern? When creating the Message, it's really

> inefficient to load ALL of the dependent objects

> (User, Signature, etc) at the same time -- I'd rather

> not load them until they're needed.

>

Take a look at the Lazy Load pattern. Also, Hibernate supports this out of the box.

> Would it make sense for the Message object itself to

> know that if its Signature hadn't been loaded, and

> someone called the get method, it should load it?

> That's what 'feels' right, but it doesn't quite seem

> to fit into the standard DAO pattern.

> i.e.,

> > public class Message {

> ... .

> public Signature getSignature() {

>if (theSignature == null) {

> // using UserDAO because signatures are owned

> re owned by users,

> // not by the Message

> UserDAO dao = UserDAO.getInstance();

> theSignature = dao.getSignature(getUser());

>}

>return theSignature;

> }

> ...

> }

>

There is a race condition in that code, but in normal circumstances it will not reveal itself.

> And c) As is hinted at above, I've also broken up the

> DAOs into logical groups -- for all user-dependent

> data access, I have UserDAO.For all

> Message-dependant access, i have MessageDAO, etc.

> I've implemented these as singletons, as I'm not

> not seeing the advantage of a factory in this case

> (one DB...) -- thoughts on that are welcome too...

>

They do not need to be SIngletons. A connection pool or logging component or cache might be, but I see no advantage (or reason) to make DAO's work this way.

> As if that weren't enough, I have another question

> around DAO, the 'business' objects and aggregate

> data.As an example, a Topic represents a

> collection of messages. The view will iterate

> through the messages in a topic and display title,

> post date, author name, and last reply info.Under

> the covers, I have the Topic as havintg a collection

> of Messages.But again, I'm stuck in the same

> situation as earlier -- the Message is expensive to

> load. I can do a query that gets me the aggregate

> data I need to display much more efficiently -- but

> that doesn't fit anywhere into my model... perhaps an

> AggregateMessage, used only within Topic?But then

> the view is driving business logic..

>

In MVC, controller and view are hard to separate. The model, on the other hand, should exist in isolatioin, with perhaps some compromises to make persistence easier. Write the model as if you had no idea of what the UI would be. Think of developing a series of black boxes that your controller and view will use.

> I've spent the better part of a day digging around

> for answers to this type of problem, and have been

> able to find very little. Any

> thoughts/ideas/suggestions are appreciated.

Best of luck.

- Saish

Saisha at 2007-7-16 1:41:29 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

> Caching is a separate issue. There are dozens of

> issues to tackle when designing a proper cache. I

> would recommend using a third-party or open source

> existing solution. Or use a cache-pluggable O/R

> mapper like Hibernate.

I'll look into it, thanks. Like I said, I was just looking throw something simple together to start with for experimentation/learning.I'll stick with the basics first, then move on to additional toolkits/etc later.

> > How do I load these aggregated objects using the

> DAO

> > pattern? When creating the Message, it's really

> > inefficient to load ALL of the dependent objects

> > (User, Signature, etc) at the same time -- I'd

> rather

> > not load them until they're needed.

> >

>

> Take a look at the Lazy Load pattern. Also,

> Hibernate supports this out of the box.

>

I'm beginning to sense a Hibernate theme here...

> > > > public class Message {

> > ... .

> > public Signature getSignature() {

> >if (theSignature == null) {

> > // using UserDAO because signatures are owned

> > re owned by users,

> > // not by the Message

> > UserDAO dao = UserDAO.getInstance();

> > theSignature =

> dao.getSignature(getUser());

> >}

> >return theSignature;

> > }

> > ...

> > }

> >

>

> There is a race condition in that code, but in normal

> circumstances it will not reveal itself.

I would assume if call #2 came in while call #1 was stil loading. "synchronized" should fix that?

>

> They do not need to be SIngletons. A connection pool

> or logging component or cache might be, but I see no

> advantage (or reason) to make DAO's work this way.

>

Well, I had them as singleton because in my current design they're also caching the data that the retrieve.Otherwise, I agree, since there'd typically be no instance data associated anyway...

> > that doesn't fit anywhere into my model... perhaps

> an

> > AggregateMessage, used only within Topic?But

> then

> > the view is driving business logic..

> >

>

> In MVC, controller and view are hard to separate.

> The model, on the other hand, should exist in

> n isolatioin, with perhaps some compromises to make

> persistence easier. Write the model as if you had no

> idea of what the UI would be. Think of developing a

> series of black boxes that your controller and view

> will use.

>

Makes sense, but it may be easier said than done. If I did that in this case, aggregate data such as would be used for presenting a list of topics would never occur to me in my design.The end result would be that the view did have to instantiate (indirectly) each invidual Message, resulting in a fairly slow implementation of the view.

Grinning_Foola at 2007-7-16 1:41:29 > top of Java-index,Other Topics,Patterns & OO Design...
# 3

> > Caching is a separate issue. There are dozens of

> > issues to tackle when designing a proper cache. I

> > would recommend using a third-party or open source

> > existing solution. Or use a cache-pluggable O/R

> > mapper like Hibernate.

>

> I'll look into it, thanks. Like I said, I was just

> looking throw something simple together to start with

> for experimentation/learning.I'll stick with the

> basics first, then move on to additional toolkits/etc

> later.

>

Hibernate is not normal JDBC. It is an 'object-relational' mapper. It allows you to write Java objects normally and then simply specify how the data should be retrieved in Javadoc annotations. I only mention it as another option.

> > > How do I load these aggregated objects using the

> > DAO

> > > pattern? When creating the Message, it's really

> > > inefficient to load ALL of the dependent objects

> > > (User, Signature, etc) at the same time -- I'd

> > rather

> > > not load them until they're needed.

> > >

> >

> > Take a look at the Lazy Load pattern. Also,

> > Hibernate supports this out of the box.

> >

>

See above. :^)

> I'm beginning to sense a Hibernate theme here...

>

>

> > > > > > public class Message {

> > > ... .

> > > public Signature getSignature() {

> > >if (theSignature == null) {

> > > // using UserDAO because signatures are owned

> > > re owned by users,

> > > // not by the Message

> > > UserDAO dao = UserDAO.getInstance();

> > > theSignature =

> > dao.getSignature(getUser());

> > >}

> > >return theSignature;

> > > }

> > > ...

> > > }

> > >

> >

> > There is a race condition in that code, but in

> normal

> > circumstances it will not reveal itself.

>

> I would assume if call #2 came in while call #1 was

> stil loading. "synchronized" should fix that?

>

>

No, it's just whenever you check if an instance variable is null, and then initialize it, there is a chance another call will come in and perform the same checks. The behavior that will happen is non-deterministic, hence a race condition. But as I indicated, the one you coded will almost certainly not pose a real-life problem. I just wanted to point it out.

> >

> > They do not need to be SIngletons. A connection

> pool

> > or logging component or cache might be, but I see

> no

> > advantage (or reason) to make DAO's work this way.

> >

> Well, I had them as singleton because in my current

> design they're also caching the data that the

> retrieve.Otherwise, I agree, since there'd

> typically be no instance data associated anyway...

>

Again, caching is a separate issue. Caches can be implemented as Singletons, and most simple, home-grown caches are. However, the fact that you want to cache should not overly influence the design of an actual DAO. Think of it this way: the cache is responsible for determining whether data is stale or needs to be refreshed. The DAO is responsible for persisting and fetching data. The two are related, but separate, tasks. One should not influence the other beyond what is absolutely necessary.

> > > that doesn't fit anywhere into my model...

> perhaps

> > an

> > > AggregateMessage, used only within Topic?But

> > then

> > > the view is driving business logic..

> > >

> >

> > In MVC, controller and view are hard to separate.

> > The model, on the other hand, should exist in

> > n isolatioin, with perhaps some compromises to

> make

> > persistence easier. Write the model as if you had

> no

> > idea of what the UI would be. Think of developing

> a

> > series of black boxes that your controller and

> view

> > will use.

> >

> Makes sense, but it may be easier said than done. If

> I did that in this case, aggregate data such as would

> be used for presenting a list of topics would never

> occur to me in my design.The end result would be

> that the view did have to instantiate (indirectly)

> each invidual Message, resulting in a fairly slow

> implementation of the view.

Sure it would. Someone has to pick a topic to use one, right? So, if you were going to offer any type of lookup functionality, this decision could be made in the absence of knowing what a given lookup screen would look like.

- Saish

Saisha at 2007-7-16 1:41:29 > top of Java-index,Other Topics,Patterns & OO Design...