DAO is Yet Another OOP Shame
Someone asked me what I think about DAO and I realized that, even though I wrote about ORM, DTO, and getters, I haven’t had a chance yet to mention DAO. Here is my take on it: it’s as much of a shame as its friends—ORM, DTO, and getters. In a nutshell, a Data Access Object is an object that “provides an abstract interface to some type of database or other persistence mechanism.” The purpose is noble, but the implementation is terrible.
Here is how it may look:
1 2 3 4 5 | class BookDAO { Book find( int id); void update(Book book); // Other methods here ... } |
The idea is simple—method find()
creates a DTO Book
, someone else injects new data into it and calls update()
:
1 2 3 4 | BookDAO dao = BookDAOFactory.getBookDAO(); Book book = dao.find( 123 ); book.setTitle( "Don Quixote" ); dao.update(book); |
What is wrong, you ask? Everything that was wrong with ORM, but instead of a “session” we have this DAO. The problem remains the same: the book
is not an object, but a data container. I quote my own three-year-old statement from the ORM article, with a slight change in the name: “DAO, instead of encapsulating database interaction inside an object, extracts it away, literally tearing a solid and cohesive living organism apart.” For more details, please check that article.
However, I have to say that I have something like DAOs in most of my pet projects, but they don’t return or accept DTOs. Instead, they return objects and sometimes accept operations on them. Here are a few examples. Look at this Pipes
interface from Wring.io:
1 2 3 4 | interface Pipes { void add(String json); Pipe pipe( long number); } |
Its method add()
creates a new item in the “collection” and method pipe()
returns a single object from the collection. The Pipe
is not a DTO, it is a normal object that is fully capable of doing all necessary database operations, without any help from a DAO. For example, there is Pipe.status(String)
method to update its status. I’m not going to use Pipes
for that, I just do pipe.status("Hello, world!)
.
Here is yet another example from Jare.io: interface Base
which returns a list of objects of type Domain
. Then, when we want to delete a domain, we just call domain.delete()
. The domain is fully capable of doing all necessary database manipulations.
The problem with DAO is right in its name, I believe. It says that we are accessing “data” and does exactly that: goes to the database, retrieves some data, and returns data. Not an object, but data, also known as a “data transfer object.” As we discussed before, direct data manipulations are what break encapsulation and make object-oriented code procedural and unmaintainable.
Published on Java Code Geeks with permission by Yegor Bugayenko, partner at our JCG program. See the original article here: DAO is Yet Another OOP Shame Opinions expressed by Java Code Geeks contributors are their own. |
Your statement that “The purpose is noble, but the implementation is terrible” is spot on, and you reinforce this statement by providing a terrible implementation. I have seen too many times an implementation which requires a separate DAO for each class where a class may be responsible for more than one table. IMHO a far better implementation is where each DAO is reposponsible for all communication with a single DBMS engine regardless of how many database or tables there are. I first came across this idea in the 1990s with a language called UNIFACE where the generation of all SQL… Read more »