Reputation: 613
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 ?
Upvotes: 20
Views: 16683
Reputation: 3144
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()
}
}
}
Upvotes: 1
Reputation: 61538
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.
Upvotes: 19
Reputation: 9971
Assuming Controller means the "C" in MVC, your third option is the right approach. Generally speaking Controller code extends or follows the conventions of a framework. One of the ideals of MVC is swapping frameworks, which is really the Controller, should be relatively easy. Controllers should just move data back and forth between the model and view layers.
From a model perspective, Controllers should interact with a service layer - a contextual boundary - in sitting front of the domain model. The UserManager
object would be an example of a piece that you would consider part of your service layer - that is the domain model's public API.
Upvotes: 0
Reputation: 2711
The Data Access Object (DAO) should be used closer to the data access layer of your application. The data access object actually does the data access activities. So it is part of data access layer.
The architecture layers before DAO could vary in projects.
Controllers are basically for controlling the request flow. So they are kind of close to UI. Although, a Manager, Handler is a bad idea, we could still add a layer between controller and DAO. So controller will pre-process the data that is coming from a request or going out (data sanity, security, localization, i18n, transform to JSON, etc). It sends data to service in the form of domain objects (User in this case). The service will invoke some business logic on this user or use it for some business logic. And it would then pass it to DAO.
Having the business logic in controller layer is not good if you are supporting multiple clients like JSPs, WebServices, handheld devices, etc.
Upvotes: 0
Reputation: 3170
for typical webapp i will prefer play framework with play's JPA and database implementation. It much more productive way.
please take a look here http://www.playframework.org/documentation/1.2.5/jpa and here http://www.playframework.org/documentation/1.2.5/guide1 and http://www.playframework.org/documentation/1.2.5/guide2
That's it))
Upvotes: -2