Is DAO pattern obsolete in Scala?
Let's consider a simple example of DAO pattern. Let Person
is a value object and PersonDAO
开发者_JAVA百科is the correspondent trait, which provides methods to store/retrieve Person
to/from the database.
trait PersonDAO { def create(p:Person) def find(id:Int) def update(p:Person) def delete(id:Int) }
We use this pattern (as opposed to Active Record, for example), if we want to separate the business domain and persistence logic.
What if we use another approach instead ?
We will create PersonDatabaseAdapter
trait PersonDatabaseAdapter{ def create def retrieve(id:Int) def update def delete }
and implicit conversion from Person
to it.
implicit def toDatabaseAdapter(person:Person) = new PersonDatabaseAdapter { def create = ... def retrieve(id:Int) = ... def update = ... def delete = ... }
Now if we import these conversions, we can write client code to manipulate Persons
and store/retrieve them to/from the database in the following manner:
val person1 = new Person ... person1.create ... val person2 = new Person ... person2.retrieve(id) ...
This code looks like Active Record
but the business domain and persistence are still separated.
Does it make sense ?
Well, I don't know anything about "obsolete" patters. Pattern is a pattern and you use it where appropriate. Also, I don't know if any pattern should be obsolete in a language unless language itself implements it with the same functionality.
Data access object is not obsolete to my knowledge:
http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
http://en.wikipedia.org/wiki/Data_access_object
It seems to me that you are still using the DAO pattern. You have just implemented it differently.
I actually found this question because I was researching whether the DAO pattern is dead in plain ol' Java, given the power of Hibernate. It seems like the Hibernate Session is a generic implementation of a DAO, defining operations such as create, save, saveOrUpdate, and more.
In practice, I have seen little value in using the DAO pattern. When using Hibernate, the DAO interfaces and implementations are redundant wrappers around one-liner Hibernate Session idioms, e.g., getSession().update(...);
What you end up with is duplicate interfaces - a Service interface that redefines all of the methods in the DAO interface plus a few others implemented in terms of those.
It seems that Spring + Hibernate has reduced persistence logic almost to a triviality. Persistence technology portability is NOT needed in almost all applications. Hibernate already gives you database portability. Sure, DAOs would give you the ability to change from Hibernate to Toplink, but in practice, one would never do this. Persistence technologies are already leaky abstractions and applications are built to deal with this fact - such as loading a proxy for setting associations vs. performing a database hit - which necessarily couples them to the persistence technology. Being coupled to Hibernate is not really so bad though since it does its best to get out of the way (no checked exceptions a la JDBC and other nonsense).
In summary, I think that your Scala implementation of the DAO pattern is fine, though you could probably create a completely generic mixin that would give basic CRUD operations to any entity (most competent devs tend to implement a "generic DAO" base class in Java, too). Is that what Active Record does?
/end of random comments/
I believe your PersonDatabaseAdapter
mutates Person
in its retrieve(id: Int)
method. So this pattern forces your domain objects to be mutable, while the Scala community seems to favor immutability due to the functional nature (or features) of the language.
Otherwise, I think the DAO pattern still has the same advantages and disadvantages (listed here) in Scala as it does in Java.
Nowadays I notice the Repository pattern to be quite popular especially as its terminology makes it look like you're dealing with collections.
精彩评论