Monday, 03. September 2007

why DAO won't die

there were some statements and blog posts about the end of the DAO pattern in the last weeks, especially in conjunction with the rising of EJB 3 and it's EntityManager. those proposals suggest to use EntityManager directly inside your business oriented services instead of encapsulating data access logic through a DAO.

i strongly disagree with this opinion. Here are some of my thoughts, why DAOs will live on:

mixing business logic with data access logic

you are tangling data access logic with business logic, especially when you have to build not only simple queries (not talking about the simple CRUD operations) but introduce i.e. more complex query building logic next to your business logik.

violation of single responsibility principle

mixing business logic and data access logic in one place gives you at least two differents reasons / causes to change.
on the one side, you may have to adapt the core business logic due to new requirements. on the other side data access logic may also change (maybe joining another table for an aggregation because of changes in the data model)

reduced readability

when you mix business logic with more complex data access logic, readability of your business services core purpose is hindered.
EntityManager provides a fixed, generic API, agnostic to your current domain context. everything within data access logic that goes beyond simple CRUD- operations has to be implemented within the service. but i only want to 'see' my core business logic in first place, not worrying about the data access logic - you should only see the WHAT, not the HOW of that data access logic. the HOW should be hidden behind a reasonable, intention revealing interface for the sake of comprehensibility.

mixing business logic and infrastructure

you are binding your business services to a special technology. i rather wouldn't mix business logic with infrastructure / technology, even if the chance is very small that technology changes, but keeping business logic free of any infrastructure (ok, this seems to be a little bit dogmatic, but binding to a special technology fixes your business logic in a very hard way, especially if you want to reuse your business logic within another technical infrastruture).

harder to test

creating mocks for EntityManager is potentially harder, since you may pass complete queries (EJB QL expressions). your mock have to inspect those query statements on a semantic level in order to behave correctly, which may be not so trivial.

lacks uniform style of representing different data sources

in a system where you have to access not only one type of data source (i.e. a relational database, an ldap database, legacy integration via message queues, ...) you'll know have different styles / levels of integration. those access logic isn't hidden behind an abstract interface any longer. but the client of those data sources shouldn't worry about the kind of data source. this should be encapsulated.
(in this case it's not the question, that it's extremely rare to replace one kind of data source with another one, but having most of times different types of data sources in parallel)

lacks uniform style of data access strategies

using EntityManager directly bounds you to the offered possibilities of its API. should you like to use JDBC in special cases or an alternative qriteria API, you'll end up with different data access technologies within your service.

violation of open closed principle

your business service is not open for extensions due to data access logic without changes, because it depends directly to the technical API. for example you can't exchange an existing data access / query building strategy (i.e. building a query string dynamically vs. using a query API) - you have to modify the business service itself, since you don't hold control of the EntityManager's implementation.

violation of dependency inversion principle

your higher level component (your business service) is directly dependend on a lower level component (EntityManager)
even if EntityManager is an interface, since you don't hold control of it's implementation (not now, not in the future), you are directly bound to it's API and it's implementation. should the interface of EntityManager change - the service has to change, too.
(if using dependency inversion principle the right way, it's not relevant if the underlying DAO interface will change, because THERE IS NO DAO interface in its own right. there is no DAO interface in its own right since the clients define there data access needs, means that there may be many DAO interfaces which belong to the different clients and not to the DAO implementation. this goes along with the interface segregation principle - see Agile Software Development by 'Uncle Bob' Robert C. Martin)

 

of course - like most design decisions - it's a matter of choosing the one or other side of a trade off. So one is right to say it depends on the context whether to use a DAO or directly include data access logic inside a business service - but you have to be clear about the consequences (which should be aligned with the projects goals which in turn should be also clear). And 'killing' the DAO comes with the mentioned ones.

Posted by mario.gleichmann at 20:37:40 | Permanent Link | Comments (17) |
Comments
1 2
1 - What you say is true if the alternative to DAO is to embed data access logic in the domain model. However an alternative that uses a data access layer which translates entities to persistence without using Data Transfer Objects is a valid alternative (IMHO)

Arnon (Comment this)

Written by: Arnon Rotem-Gal-Oz at 2007/09/03 - 22:44:13
2 - i agree with you about all of it, but there is always one thing i didnt understand about DAO, why we should use interface with DAO? for me really complicates development, because first i write method in DAOImpl class and then i have to add it to interface. I never saw two implementation of DAO interface(in test you can subclass). Isnt it just about being cool and using extra interfaces?(i know that some people to feel sexy use interface for every class) because you can always subclass the main DAO class and throw exception for not implemented method, so i heard because i never done it. you might say its alot of work and you might forget some methods, but for me that never happens,but i always need to extract method to interface. (Comment this)

Written by: Anonymous at 2007/09/03 - 23:20:28
3 - Anonymous just for you information, I current work for a projet where we have 3 DAO implementations
--> hibernate
--> xml rpc (platform X)
--> soap (platform Y)
In such case you use an interface of course ... By anyway programming against interface is the way to go ... unless it is a pain, as does not give you anything :)
If you will only use 1 dao, well ... just skip the interface part, you'll be happy too :D

Enjoy your day (Comment this)

Written by: opensourcereader at 2007/09/04 - 02:15:59
4 - DAO's will not die any time soon. Persistence and data access are not one and the same. How you use the two depends on your application architecture. If you are using a layered architecture for your application then your business model should be isolated from technology and loosely coupled to other layers. From a data access perspective this means isolation from JDBC, EJB, Hibernate, JDO, and the like. It's all about having transparent data access. DAO's provide this isolation and transparency through interfaces, regardless of the type of data, storage mechanism, and access API.

Persistence frameworks and API's would have to provide very flexible data access through very indirect means for there to be no need for DAO’s.
 (Comment this)

Written by: WarpedJavaGuy at 2007/09/04 - 03:02:26
5 - fully agree with the article, JPA is a cool persistence technology but nothing more than that (Comment this)

Written by: Anonymous at 2007/09/04 - 08:02:26
6 - Thanks for finally giving me an example of different datasources.


Do all those datasource-provider-classes implement the same interface? Like..

"public Object getFancyObject(Long id);" ?


And you have ORM/soap/xml rpc implementations for different platforms/use-cases?



Thank you for expanding my horizon on this. I never thought about structuring an application with those kind of datasources in mind. But then again, I have in previous projects not been confronted with those kind of reqs. (Comment this)

Written by: Anonymous at 2007/09/04 - 10:03:39
7 - Hi Anonymous,
Yes all my database-provider-classes implement the same interface.
However in such case a "public Object get(Pk)" does not means anything when you are using different datasources.
The only way to go is get(Object), and the DAO implementation will be responsible for the right strategy to retreive the object.
For instance the hibernate dao does get(object.getPrimaryKey) and my soap does remote.get(object.getRemotePrimaryKeyStoredInMyLocalDB)

Enjoy your day
 (Comment this)

Written by: opensourcereader at 2007/09/04 - 11:25:16
8 - Well
DAO as Interface implementation is used to make the code more portable.
Its easier to invoke code via just getting a handle than actaully creating an object.
Plus interface really lay a strong foundation for creating N-tier system.

So its more of a practical approach.

For example tale a ClentServer App.
If we use your methodology of not creating interface then we have to port the implementation class to client side too.
Where as not in the interface implementation case and also effect of further changes to implementation
would only reflect on server side.




 (Comment this)

Written by: koodude at 2007/09/04 - 13:32:40
9 - I agree with what you say. On the other hand, Java EE has suffered of so much boiler plate code, design patterns that turned into anti-patterns, complexity and so on, that I have no problem in using EntitManager CRUD operations on my EJBs. For simple application, I skip the DAO pattern, otherwise, I keep on using it for the reasons you've mentioned. (Comment this)

Written by: Antonio Goncalves at 2007/09/04 - 16:30:09
profile
10 - Arnon,

i'm not quite sure what you mean by embedding data access logic within the domain model. Do you suggest to include basic persistence operations like 'store' or 'load' into your business objects? Personally, i wouldn't recommend to make your business objects aware of an non-business issue like persistence or even bound them to a certain persistence strategy. I would rather keep my business objects clean of any infrastructure issue. That said in this point of view, persistence looks more like an crosscutting concern to me, that i wouldn't mix with business logic.

To your second statement - again i'm not sure if i understand you right: DAOs are NOT related to Data Transfer Objects. Far from it. Personally, i rather would go with a rich domain model, including behaviour rich business objects instead of anemic, 'dumb data continers'. Even in the scenario of a rich domain model, DAOs make sense, since you are still in need of encapsulating access logic in an intention revealing way, supporting the mentioned principles.

Regards

Mario (Comment this)

Written by: magle at 2007/09/04 - 19:33:40
Write a comment






1 2