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)
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.