I wanted to propose a design pattern I've come up with. I haven't seen it used before which is surprising since it fixes a common problem, so I was wondering if I just haven't found it, or whether my solution is undesirable or breaks any major design principles. If anyone could provide me with any links to where it's been described, or provide opinion or critique. If you have none then feel free to use =)
I often use the Active Record Pattern due to it's simplicity, fully aware of the undesirable coupling it creates on the database, and litters domain objects with ugly SQL code. So my proposition is the following:
interface IUser{
getFirstName();
getLastName():
setFirstName();
setLastName();
}
class User implements IUser{
id:string;
firstName:string;
lastName:string;
constructor(id:string, firstName:string, lastName:string){
this.id=id;
this.setFirstName(firstName);
this.setLastName(lastName);
}
function getFirstName(){
return this.firstName;
}
function getLastName(){
return this.lastName;
}
function setFirstName(firstName:string){
this.firstName=firstName;
}
function setLastName(lastName:string){
this.lastName=lastName;
}
}
class UserDB implements IUser{
user:IUser;
constructror(user:IUser){
this.user=user;
}
function getFirstName(){
return this.user.getFirstName();
}
function getLastName(){
return this.user.getLastName();
}
function setFirstName(firstName:string){
this.this.setFirstName(firstName);
this.update();
}
function setLastName(lastName:string){
this.setLastName(lastName);
this.update();
}
function update(){
// sql execution script
// update user set first_name=getFirstName(), last_name=getLastName() where id=this.user
}
}
An then in code which creates instances, whether it be a factory or repo of User would then do this:
function getUser(id:string):User{
// select first_name, last_name from user where id=id;
var user=new User(id, firstName, lastName);
var userdb=new UserDB(user);
return user
}
This is perhaps a bad example since typically a User doesn't change their first or last name but it was the simplest example I could come up with!
I am essentially using the GoF Decorator pattern, but have never seen it used this way for data access.
It still has the undesirable effect of performing a db access per property update, just as the active record pattern does, but doesn't it at least remove the coupling from the User class to the database and removes the ugly SQL code. The UserDB implementation could go in the same package as other data access classes. Does the solution unbreak the SRP principle from the Active Record Pattern. I know that Active Record Pattern is considered by some to be an anti-pattern, but it is easy to use on simple applications, so point is just the following, if you ARE going to use it, wouldn't this is a better implementation for it?
Edit to respond to Matia's comments:
Matias, thank you very much for your comments, critique is exactly what I was looking for. However, I don't agree with your conclusions and let me explain why:
Firstly take a look at your sample User class, it is a domain entity but yet has implications of data storage. A domain object shouldn't have a save() method on it. Where as my example (the User class) truly is a domain object. Domain objects shouldn't have dependancies on repositories, especially in a constructor(!) Repositories are concerned with data storage concerns, so you're immediately declaring to the world that the User domain object is concerned about persistence. In addition a User instance shouldn't know about how to persist itself or how to retrieve other User instances - so this is another major violation.
Whilst I know people do reference Repositories from domain objects, this is considered very bad practice, and there are MANY references to this all over the internet, here are a couple links for convenience:
Is it ok for entities to access repositories?
http://thinkbeforecoding.com/post/2013/03/03/Entities-and-Repository-injection-ndash%3B-follow-up
Please do look at those links if you continue to believe that it is ok for the User class to reference the User Repository, or please share with me any link which arrives at the opposite conclusion.
"Single Responsibility Principle. Your active record owns the persistence logic."
You're absolutely right, UserDB owns persistence logic, but that is exactly what Active Record Pattern is supposed to do, and remember I'm comparing my solution with that one.
But what I have done and the whole point of my proposal is to decouple that persistence logic dependancy from the domain layer, thereby removing SQL from it, since UserDB will reside in a data access layer, allowing my User class to truely belong in the domain layer, whereas yourexample User class could not.
"Dependency inversion principle. You create dependencies on implementations rather than on abstractions."
Regarding depending on a concrete class, I assume you're referencing to the fact that I'm extending the UserDB class from the concrete User class? I was aware about the concrete dependancy, but this could be easily eradicated by introducing an IUser interface and having both User and UserDB implement it, but I was trying to keep the code minimal for the purposes of presentiation and convenience. So I do recognise and agree with that point, however it is easily rectifiable.
"As you can check in my sample, I'm not persisting active record's changes whenever a property is set, but it's done when User.Save() is called, which seems to be a better approach."
If performance is a concern, then I would consider not calling it on each property update, but it again would reside in UserDB and not the User class as your sample does, for reasons I think I've already explained.