Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DAO pattern and model objects

I have looked up a lot of information about the DAO pattern and I get the point of it. But I feel like most explainations aren't telling the whole story and by that I mean where would you actually use your DAO. So for example if I have a User class and a corresponding UserDAO that is able to save and restore users for me, which is the correct way:

  • The controller creates the User object and passes it to the UserDAO to save it to the database

  • The controller creates the User object and in its constructor the user object makes a call to the userDAO in order to save itself into the database

  • This is a code smell and you are missing an extra class "UserManager" which the controller will ask to create the user. The UserManager is responsible for creating the user and asking the UserDAO to save it

I really feel like the third option is the best, because all that the controller is responsible for is delegating the request to the correct model object. What is your favorite way? Am I missing something here ?

like image 511
Tom Avatar asked Jul 27 '12 13:07

Tom


People also ask

What is the DAO design pattern?

DAO Design Pattern is used to separate the data persistence logic in a separate layer. This way, the service remains completely in dark about how the low-level operations to access the database is done. This is known as the principle of Separation of Logic.

What is a DAO in programming?

The Data Access Object (or DAO) pattern: separates a data resource's client interface from its data access mechanisms. adapts a specific data resource's access API to a generic client interface.

What is the difference between DAO and Repository patterns?

DAO is an abstraction of data persistence. However, a repository is an abstraction of a collection of objects. DAO is a lower-level concept, closer to the storage systems. However, Repository is a higher-level concept, closer to the Domain objects.


2 Answers

From my experience with DAOs, the first approach is the only correct one. The reason is that it has the clearest responsibilities and produces the least clutter (well, some very respectable programmers regard DAOs themselves as clutter. Adam Bien sees the original DAO pattern already implemented in the EntityManager and further DAOs to be mostly unnecessary "pipes")

Approach 2 binds the model to the DAO, creating an "upstream dependency". What I mean is that usually the models are distributed as separate packages and are (and should be) ignorant of the details of their persistence. A similar pattern to what you are describing is the Active Record pattern. It is widely used in Ruby on Rails but has not been implemented with equal elegance and simplicity in Java.

Approach 3 - what is supposed to be the point of the UserManager? In your example the Manager performs 2 tasks - it has the duties of a User factory and is a proxy for persistence requests. If it is a factory and you need one, you should name it UserFactory without imposing additional tasks on it. As for the proxy - why should you need it?

IMHO most classes named ...Manager have a smell. The name itself suggests that the class has no clear purpose. Whenever I have an urge to name a class ...Manager, it's a signal for me to find a better fitting name or to think hard about my architecture.

like image 130
kostja Avatar answered Oct 01 '22 21:10

kostja


For the first approach; IMHO, controller calling a method on a DAO object is not a good design. Controllers must be asking "service" level objects about business. How these "services" persist the data is not a concern for the controller.

For the second approach; sometimes you may want to just create the object, so constructor duty and persisting duty must not be tightly coupled like this.

Lastly, the manager or the service objects is a good abstraction for the layered architecture. This way you can group the business flows in the appropriate classes and methods.

But for Play, companion objects of case classes are also a good candidate to use as DAO. The singleton nature of these objects make it a good candidate.

case class TicketResponse(appId: String, ticket: String, ts: String)

object TicketResponse{
  implicit val ticketWrites = Json.writes[TicketResponse]

  def save(response: TicketResponse) = {

    val result = DB.withConnection {
      implicit connection =>

        SQL("insert into tickets(ticket, appid, ts)"
          +   " values ({ticket},{appid},{ts})")
          .on('ticket -> response.ticket, 'appid -> response.appId, 'ts -> response.ts).executeInsert()
    }

  }

}
like image 24
LostMohican Avatar answered Oct 01 '22 20:10

LostMohican