"DAO coding paradigms can require some skill" is a sentence that presently appears at Wikipedia in the description of Data Access Objects. I find DAOs very useful and honing the skill is worth it. The article goes on to state a benefit being, "Improved efficiency and performance of the data layer since it is standard reusable software".
The majority of DAO implementations that I see tend to provide similar functionality to the Active Record pattern i.e. CRUD. Unfortunately these DAOs do not achieve the benefit of improved efficiency and performance. Let's say I have a customer, with orders that relate to products. My use-case is that I want the customers along with the orders and their products. With a straight CRUD approach I tend to get the customers (c) and then I get the orders (o) and then I get the products (p). That's potentially c * o * p or more requests on the database over the network.
The method signatures of my DAOs are shaped by the service layer that drives them. Here are a few methods of one of my real-world DAOs to serve as an example:
public void createSMSSubscription(
String msn, String flightNo,
String actualText, String receivedParsedText,
Date scheduled, Date eventTime,
AbstractSMSEvent subscriptionEvent) {
public Collection<Subscription> getActiveSubscriptions(
AbstractRenderedFlight renderedFlight) {
public Collection<ReceivedSMSFlightSubscription>
getCurrentReceivedSubscriptions(
String msn, Date receivedTime) {
It may be that the service layer simply asks for a Customer to be created, but more often than not, the methods tend to be tailored to what the service layer wants to do e.g. "create an order for a customer that exists and only for products that exist", or "create an order for a customer that has not exceeded their credit limit" and so forth. I like to have my DAOs do as much as possible at the database with the objective of minimising the number of calls made to it. In short, my DAOs tend to comprise of fairly coarsely grained functions instead of finely grained CRUD style operations. I'll admit that it is a bit of an art in getting the granularity correct and that re-factoring commonly occurs, but the overriding goal is to reduce the IO between my logic layer and the data layer. Performance and efficiency then typically follow.
My DAOs are developed as the service layer evolves i.e. they are not developed before the service layer. As stated above I let the service layer determine what functionality the DAO should provide. If I've developed a service with the DAO development alongside, and then develop another service that wants more out of the DAO then I tend to done one of two things:
- parameterise the existing methods of a DAO such that their behaviour can be varied; or
- create new methods on the DAO.
One more thing while I'm thinking about DAOs... they're a great place to encapsulate persistence functionality of course. It used to be that we may have wanted to hide away the differences of dealing with multiple types of relational database. However we now find ourselves thinking about providing non-relational stores (NoSQL) as well. DAOs give you the freedom to choose the best persistence implementation to suit your application's requirements.
Long live the DAO!