DAO Is yet Another OOP Shame
yegor256.com
yegor256.com
I also read the guys arguments against how ORMs are still SQL like, I contend that's caused by most (non functional?) languages not treating querying against collections as first class citizens.
I'm a big fan of C# and my favorite feature is Linq. With Linq you can query any data source using native type safe C# syntax, pass Linq expressions around and they will get translated on the fly to a query language that the source understands. You can send your Linq expression to sql Server, Mongo etc in production and mock out your source in your unit tests to use Lists and still test your queries.
There’s also multiple ways to implement and having a DAO that spits out transfer objects or value objects that aren’t connected to the db is perfectly fine and nice and OOP.
In some situations with complex data structures that require lots of transactions the DAO becomes more important.
In the end, Im not sure what the article complains about. Author shows a simple example as being bad, but doesn’t show an example where it’s needed. And the negative isn’t substantial.
If anything it gets you thinking more like the database system and that could be a pain if you switch off of relational or between systems that represent data differently.
It seems that the way an ORM abstracts talking to the database is not the way he would like it to happen. So he makes his own custom abstractions that involve sending raw sql strings instead. That's better?
It makes it harder to ramp people up when you aren't using a popular package (preferably open source with an agreeable license) and there is usually only that one person in the company that understand it's weird quirks instead of being able to Google for a solution to a problem.
Book, in the presented example, has no behaviour so it is a DataStructure, making it an object introduces needless overhead.
Also, I believe DAOs are intended to be used in more complex cases. For example, I may have a BookSeries class in my database, and I may want it’s instances to have a numberOfBooks property. NumberOfBooks would be a computed value, and it would be the job of the DAO to populate that field when retrieving the BookSeries.
This could go even further, where a class exist that does not map to the database table at all.
Do you mind expanding on this a little bit? I am very confused. A "data structure" is an implementation of an abstract data type (https://en.wikipedia.org/wiki/Data_structure). A "class" is also an implementation of abstract data type (from this book https://www.amazon.ca/Object-Oriented-Software-Construction-... page 165).
I am not sure how you can have a data structure Book without any operations. Even if it were a C struct, accessing a field would consist an operation around that data structure.
Several years ago, I wrote an application using the repository pattern and there were repositories everywhere. But they seemed like a step up from the unstructured chaos of the DAO. It was a bigger mess when all was said and done.
Having struggled through the same issues as the author, I can say that after having learned and applied and DDD, CQRS, and Event Sourcing, I don't see the problem anymore. My concerns are one or more levels above "how do I write to or read from the database?". The database becomes a technical implementation detail and not the cause of crisis in architecting a system. In the past few months, I've used EF as an ORM, EF using just stored procedures, and Dapper, both through a DAO interface. All of these solutions worked and were easy to implement because I was simply recording changes to data, not putting the data at the heart of my logic.
I encapsulate all database access, including dealing with connections and transactions; I have a single point of authority regarding where data come from and how I call update operations; and all objects coming in or out of the DAO are free of database dependencies (no persistence nonsense).
DAO/DTO designs, in my experience, tend to go bad when there's inappropriate repetition and complication: slightly different validation in different operations, validation in client code, multiple similar queries without consolidation, unwarranted different classes used in different cases, translation between back-end dumb containers of data and marginally different front-end dumb containers of data instead of thinking about a proper data structure, and so on.
From my personal experience, I've found that trying to write database interaction methods on an object seemed to result in (subjectively) messier and harder to maintain code, compared to using functions that take or return objects. To achieve Encapsulation, I'd merge this into functions `static void update(Book b)` or `static Book get()` within the `Book` class.
Though, this preference comes from having been corrupted by functional principles and a strong preference for immutable data objects.
[1] https://www.coindesk.com/understanding-dao-hack-journalists/