I'm not sure I wholly agree. I think Lachlan's approach has far more benefits than drawbacks.
Consider this:
PHP Code:
class DomainObject {
protected $mapper;
public function __construct(DataMapper $mapper) {
$this->mapper = $mapper;
}
public function save() {
$this->mapper->save($this);
}
}
class DataMapper {
public function findById($id) {
//get data from the source
$result = array(); //query the database, read xml file, get the data from somewhere
$obj = new DomainObject($this);
foreach ($result as $key => $value) $obj->$key = $value;
return $obj;
}
public function save(DomainObject $obj) {
//put $obj back into the database, or wherever it came from
}
}
The domain object knows it can be persistent (is this a really a bad thing?). What it doesn't know, is anything about how the mapper works.
Pointless? In this example yes.. but introduce realations and it becomes incredibly powerful. By defining relations in the mapper (how a mapper relates to another mapper) it makes this:
PHP Code:
$user = $userMapper->findById('123');
echo $user->orders[0]->items[0]->product->manufacturer->name;
Both possible and easy. This is how my own ORM works 
The alternative is messy and involves initiating a whole load of mappers manually with code that is clearly wrapping a relational schema or fetching the entire database into the $user object.
Any of these mappers could be database/xml/flat file/web service. It doesn't matter.
Should the domain object know it might be persistent? It does not cause any problems. You mention testing, in this example you'd use a mock DataMapper.
Should the domain object know the method of persistence or any implementation details of it? No.
Bookmarks