user = new User();
user.setFirstName("Tony");
user.setLastName("Nelson");
user.save();
This type of code follows the Active Record design pattern, where domain objects contain your CRUD operations.
Hibernate, which acts as a Data Access Object, takes a slightly different approach. Rather than having the object save itself, Hibernate performs the CRUD.
user = entityNew("User");
user.setFirstName("Tony");
user.setLastName("Nelson");
entitySave(user);
Since Hibernate has become the ORM of choice in ColdFusion, I've decided that an object should not know how to save itself. Now with that in mind, should an object know how to populate itself? Consider the following code:
user = new User();
user.setFirstName(arguments.firstName);
user.setLastName(arguments.lastName);
user.setEmail(arguments.email);
user.setPassword(arguments.password);
user.setBirthDate(arguments.birthDate);
user.setGender(arguments.gender);
user.setHeight(arguments.height);
etc...
Pretty sure we've all seen code like this, where you're just taking all the arguments and calling their corresponding setters by adding "set" in from the argument name. Wouldn't it be a lot simple to just do:
user = entityNew("User");
user.populate(arguments);
entitySave(user);
But again, since a user shouldn't know how to save itself, it probably shouldn't know how to populate itself either, which gives us:
user = entityNew("User");
entityPopulate(user,arguments);
entitySave(user);
Mmmm... entityPopulate() would be a handy little tool. Now what about validation? Same theory applies...
user = entityNew("User");
entityPopulate(user,arguments);
errors = entityValidate(user);
if(ArrayLen(errors) == 0) {
entitySave(user);
}
Well it's short, although I'm not sure it's entirely clear what we're saving since it's so generic. But again, maybe that's a good thing. Ideally, you could get rid of all the "entity" stuff and make a really generic Service that looked like this:
user = new("User");
populate(user,arguments);
errors = validate(user);
if(ArrayLen(errors) == 0) {
save(user);
}
That almost looks as good as pseudo-code, with the only thing that's a little code-y being ArrayLen(errors). Speaking of which, there should be a generic length() function that can accept an array, query, struct, or string and return its length, regardless of data type. Man, that would be pretty sweet. Then the code would look even shorter.
user = new("User");
populate(user,arguments);
errors = validate(user);
if(length(errors) == 0) {
save(user);
}
Seems pretty clean. Just for fun, how would that look using smarter objects and a little method chaining?
user = new("User").populate(arguments);
errors = user.validate();
if(length(errors) == 0) {
user.save();
}
Not too shabby. And now you see my struggles.