terms. There's also an excellent chapter on persistence using
NHibernate. A lot of the concepts he's referring to can be applied
using a Doctrine / Zend backend (Doctrine seems a little more mature
than Zend_Db IMO)
On 29-Jul-08, at 10:03 AM, Bryce Lohr wrote:
> Hi Marian,
>
> Certainly, PoEAA has been an extremely helpful resource for me, but
> beyond that, most of what I've gathered has been scattered across
> blogs and articles over time. There are a few books, such as Data
> Modeling Patterns by David Kay and Domain-Driven Design by Eric
> Evans, that are on my to-buy list, but I haven't bought them yet. :)
>
> Regards,
> Bryce Lohr
>
>
> Marian Meres wrote:
>> Hey Guys,
>>
>>> as it's probably the most helpful conversation I've ever had about
>>> domain logic.
>>
>> I absolutely agree and I just don't want this thread to end...
>>
>> Besides already mentioned Martin Fowler's book (just bought it),
>> what books/resources would you suggest are worth reading on this
>> subject?
>>
>> Ideally something more conceptual/philosophical (rather than too
>> concrete, with some examples though), web application oriented if
>> possible... (I have not "googled" anything yet.)
>>
>> Thanks again for inspiration.
>>
>> Regards,
>> Marian
>>
>>
>> On 28.7.2008 18:54, 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
>
没有评论:
发表评论