views:

153

answers:

2

Me and my colleagues got into this discussion early this morning, and our opinions started to clash a bit, so I decided to get some impartial advice here.

One of my colleagues reckons that the DAO should return an object (populated bean). I think it's completely fine when you're returning a recordset with only one line, but think it's overkill if you have to return 10 lines, and create 10 separate objects.

I on the other see that the difference between DAO and Gateway pattern is that the gateway pattern will allow you to return a recordset to your business class, which will therefore deal with the recordset data and do whatever it needs to do.

My questions here are:

  1. Which assumptions are correct?
  2. What should the return type be for a DAO (i.e. getContact() - for one record)
  3. Should getContacts() (for multiple records) even be on the DAO, if so, what's it's returntype?

We seem to be having some sort of confusion about DAO and Gateway Patterns. Should they be used together?

Thanks in advance

+1  A: 

This is a design pattern, and the most important thing is to be consistent. In my opinion, DAOs should return business objects and not return record sets unless there is a VERY good business reason to avoid doing this. If a function potentially returns more than one object, it should return a Collection of objects. Better yet, use a framework like JPA or hibernate so you can let a framework take care of persistence.

Jay
But wouldn't a collection of objects be a bit of overkill, and really memory intensive?
Marcos Placona
Object Relational Mappers like JPA, Toplink, and Hibernate are pretty efficient frameworks. I generally feel that using your object hierarchy is preferred unless you have shown, through use, that it is not efficient enough for a given page. If you have shown that, it may very well mean you have implemented a poor hierarchy for the business needs of the application.
Jay
Consistency in itself is not a goal. It is desirable to have some level of consistency, but rigorous consistency can bring inflexibility and compromised design choices. If there are good reasons, break out of the pattern.
mdma
+7  A: 

The gateway pattern is concerned with providing a single point of access for a system or subsystem. The DAO pattern is a specific type of gateway - it provides the sole means of getting a particular type of data from the data store.

I'll answer the questions directly, here and expand upon the answers below.

1. Which assumptions are correct. The DAO patten is concerned with hiding the details of fetching entities and queries over entities. Returning a recordset that is directly tied to the persistence mechanism is generally not a good idea since it breaks the abstraction. By keeping the DAO storage-agnostic, testing is much simpler - it is then possible to mock the DAO interface using for example a simple in-memory implementation based on test data stored in collections.

2. What should the return type be for a DAO (i.e. getContact() - for one record) The return type should be Contact bean. As you add attributes to the contact, only the Contact class needs to change - the DAO interface stays the same.

3. Should getContacts() (for multiple records) even be on the DAO, if so, what's it's returntype? I put query methods alongside other DAO methods - I don't really see a distinction. Multiple contacts can be returned as a List or appropriate Collection of Contact beans.

The debate about returning objects or just the needed values is one of extensible design and performance. The default choice should be to return Beans. Most ORM mappers and even JDBC access layers make creating objects relatively lightweight (modern JVMs can create a new object in under 10 CPU instructions), and it is by far the best design choice, and will evolve easily.

Returning non-object results, such as a list of CustomerIDs is a possibility, but should be taken when there is clear evidence that it is necessary. Performance is usually the motivating factor, and so the design should be backed up with profiling evidence. Otherwise this is likely to be sacrificing good design in favor of premature optimization. Extending a design that returns non-object data can be difficult - say you want now to return the customer ID and the last order date. If you are returning data as rows and primitive types, then the shape of the return type is going to change, typically requiring the methods on the DAO interface and implementation to change, and all clients that use them. With a bean, related data can be fetched without changing the shape of the data - assuming the related data is available starting from the bean already being returned.

The beans do not need to be fully populated. ORM mappers tend to lazily fetch related objects and collections, so you take the performance hit for what just what you retrieve.

To sum up, while it is possible to have a mix of methods returning bean and non-bean results, I would steer away from the non-bean results unless there is a compelling reason to do so. And do so with awareness of the maintainance issues this may cause.

mdma
Great answer, this really made me see thing in another way, and made me think that perhaps I'm sometimes worrying too much about the premature optimization. However, I still remain a bit sceptical about lazy-loading, and how it affects the memory usage in an overall. Thanks a lot
Marcos Placona