This approach seems to me like it may be a good way to attack the
particular problem of querying and persisting Travel_Agent/Travel_Trip
objects that Adam originally mentioned several posts back in this thread.
Regards,
Bryce Lohr
Jonathan Lebensold wrote:
> Hi Adam,
>
> I've found that the Repository Pattern (PoEAA) has done me a lot of
> good in medium-scale projects. When you might have a complex
> underlying data model (with 1-m m-m and 1-1), it doesn't make sense to
> expose multiple aggregate roots (ways of persisting) since it
> complicates the interaction between the controller, which is
> interesting in client interaction, and the persistence of data.
>
> I start out by identifying aggregate roots and create repositories
> around them. These repositories serve up data transfer objects (which
> can be Doctrine or Zend_Db data objects) and then persist them.
>
> The big advantages to this approach are thin controllers and
> transactionality since repositories, by definition have a unit of work
> associated with them. For me, its the Repository that provides the
> "coarse api" that Bryce was referring to. If you're clever, you can
> store multiple data transfer object types in one repository's Unit of
> Work, thereby doing commits atomically.
>
> Also, Zend_Form helps keep things thin. On my own projects, I've
> managed to keep a small controller for complex forms by doing
> validation in Zend_Form and flushing out the persistData() method
> (which in turn fires against the Repositories in question). So with
> the example you gave, I would've relegated that to a
> Zend_Form-inherited object's persistData() method.
>
> This way, the repositories, as the project grows, can be refactored
> into classes that live inside inside the domain, which can be tested
> and that the controller doesn't need to deal with.
>
> my 2 cents,
>
> Jon Lebensold
> http://jon.lebensold.ca
>
> On 28-Jul-08, at 11:58 AM, Bryce Lohr wrote:
>
>> Hi Adam,
>>
>> Adam Jensen wrote:
>>> 1. A good domain model is unaware of its own underlying data source
>>> (or even that it has one), and therefore cannot really be responsible
>>> for its own persistence.
>>> 2. Code using the domain model (e.g., a controller action) shouldn't
>>> really be aware of the technical details of persistence either.
>>>
>>
>> This is where the philosophy part comes in to play: your rule #1
>> precludes perfectly valid patterns, such as Active Record, that
>> "know" something about the data source structure. You have to decide
>> based on your own philosophy, the app's requirements, and the
>> trade-offs of different data source strategies, which approach is
>> really the most useful.
>>
>>> [code]
>>> public function someAction()
>>> {
>>> // The Mapper here is the only object that knows
>>> // anything about the underlying data source.
>>> $mapper = new Travel_DataMapper();
>>>
>>> // Use the mapper to retrieve an existing domain object
>>> $model = $mapper->findTrip(14);
>>>
>>> // Change some arbitrary data
>>> $model->traveler = 'Adam';
>>> $model->departure = '2008-09-01';
>>> $model->getDestinationByOffset(2)->country = 'MX';
>>>
>>> // Pass the modified domain object back to the mapper for
>>> persistence
>>> $mapper->save($model);
>>> }
>>> [/code]
>>>
>>> This seems ALMOST correct to me, but I'm still not sure I'm entirely
>>> satisfied. The thing is, the controller is now aware of the
>>> persistence layer, which seems to violate rule #2 above.
>>>
>>
>> To me, this doesn't violate rule #2 (based on my very superficial
>> knowledge of what you're trying to achieve). Here, the data mapper
>> has a fairly abstract interface that doesn't appear to tie you to any
>> specific data source structure other than one identifying Trip
>> objects by an integer. This would probably be flexible enough for
>> most of the examples I've seen so far in this thread.
>>> Then again, although the controller is aware of the persistence layer,
>>> it doesn't know anything about the details of the persistence process.
>>> So maybe it's not the worst thing in the world...after all, it seems
>>> like persistence in a web application is mainly necessary due to the
>>> stateless nature of HTTP transactions, and HTTP transactions are the
>>> bread and butter of the controller layer.
>>>
>>
>> I agree: in MVC web applications, I think the controller's main job
>> is to translate HTTP requests into some form of request upon the
>> application's domain model, and then to express the domain model's
>> results as something meaningful in HTTP. This means managing the
>> interaction with domain model objects, and persistence is still part
>> of the model layer.
>>
>> That said, if you want, you can use something like a Service Layer
>> [1] to cleanly separate the HTTP-specific code from the domain-object
>> management code. Use the Service Layer as a facade to create a very
>> coarse API that would roughly correspond to what each controller
>> action needs to do with the domain model. You'd have to decide if
>> this would really be worth the effort for your application.
>>> Anyway...I really appreciate the continued discussion here...we almost
>>> ought to turn this into a tutorial, as it's probably the most helpful
>>> conversation I've ever had about domain logic. Even the philosophical
>>> parts...turns out I actually have a philosophy degree, so that's right
>>> up my alley :)
>>>
>>> Thanks!
>>> Adam
>>>
>>
>> Hope this helps,
>> Bryce Lohr
>>
>> [1] http://martinfowler.com/eaaCatalog/serviceLayer.html
>>
>> August 1st is National Minority Organ Donor Awareness Day
>>
August 1st is National Minority Organ Donor Awareness Day
没有评论:
发表评论