views:

1336

answers:

1

I asked this question a while back but now I'm looking to implement an actual separation between my database access layer and the domain layer. I am also going to be working to move business logic into the domain where it belongs and out of the controller scripts.

I'm using Zend Framework which implements the Table Data Gateway and Row Data Gateway patterns for the data access layer, but it apparently fails to really define how to build a domain layer that is separate from the data access layer. I've considered using an Active Record pattern where the domain logic coexists with the data access logic, but I have the following situation that occurs at least once that I don't think Active Record will handle:

I have a single table "Person" which contains person_id and userType fields.

Each userType (admin, buyer, associate, supervisor) has specific business logic associated with it and all types inherit some basic functionality from a Person object.

I don't want to bloat the Row Data Gateway object with business logic that belongs specifically to just one type of user but I'm not certain how to construct the domain layer to represent the different types of users. For example, do I make a Person object that contains the PersonGateway object and then write wrapper functions that pass calls to the gateway object, or do I write the Person object to extend the PersonGateway object and then only implement the specific functions that I need?

Likewise, I would typically think that this is (in part) a factory problem where I need a factory method that will instantiate the correct sub-class based on userType. Is that still the best method here with Zend Framework's Zend_Db class?

Any suggestions or links to tutorials that talk about how to properly create a domain model on top of Zend_Db would be greatly appreciated.

+9  A: 

Domain Models extend nothing. They're just plain classes you use to encapsulate business logic. They may use data access objects, so there may be a protected instance of a row data gateway object inside the class. A Row object usually represents an instance of the domain more closely than a Table object. Besides, you can always get the Table object with the Row's getTable() method.

Typically DM classes have an interface with methods corresponding to higher-level operations you can do with that class. But you don't necessarily want to surface all data access operations.

class Person {
  // Zend_Db_Table_Row object
  protected $data; 

  public function subscribeToService(Service $service) { ... }

  public function sendMailTo(Person $recipient) { ... }

  public function changePassword($newPassword) { ... }
}

I also blogged about this subject last spring, and wrote about it on the ZF mailing list recently.

As far as tutorials and resources, try http://domaindrivendesign.org/

Bill Karwin
Thanks Bill. I was waiting for you to respond. I've read most of your other responses to questions about Zend Framework.
Noah Goodrich
To my thinking, this is more about OO methodology, not solely ZF. Domain-Driven Design applies to Ruby on Rails, Django, J2EE, the gamut!
Bill Karwin