OOP App Architecture: Which layer does a lazy loader sit in?
I am planning t开发者_如何转开发he implementation of an Inheritance Mapper pattern for an application component http://martinfowler.com/eaaCatalog/inheritanceMappers.html
One feature it needs to have is for a domain object to reference a large list of aggreageted items (10,000 other domain objects)
So I need some kind of lazy loading collection to be passed out of the aggregate root domain object to other domain objects.
To keep my (php) model scripts organised i am storing them in two folders:
MyComponent\
controllers\
models\
domain\ <- domain objects, DDD repository, DDD factory
daccess\ <- PoEAA data mappers, SQL queries etc
views\
But now I am racking my brains wondering where my lazy loading collection sits. It seems to stride both layers. Internally its a kind of data mapper, externally its a domain object.
Any suggestions / justifications for putting it in one place over another another?
- daccess = data access
- DDD = Domain Driven Design Patterns, Eric Evans - book
- PoEAA = Patterns of Application Architecture Patterns, Martin Fowler - book
The simple answer is that it probably sits in your DataAccess layer.
//Domain Object
class Store {
public function GetGiantListOfProducts() { }
}
//DataAccess Object
class LazyLoadingStore extends Store {
public function GetGiantListOfProducts() { // function override
// data access code
}
}
Then, your DAO might look like this:
class StoreProvider {
public function GetStoreById($id) {
//User expects a list of Store, but you actually return a list of LazyLoadingStore - nobody need know the difference
}
}
The more complicated answer is - this reeks. Do you really need to lazy load stuff? It might be a better idea to re-examine your aggregate roots. Perhaps you don't need a $store.GetGiantListOfProducts() method at all and could gracefully sidestep the entire problem by changing the relationship traversal where each Product has a GetStore() method and you get a list of products like so:
class ProductProvider {
public function GetAllForStore($store) {
// return list of products for the store
}
}
On the other hand, if the relationship has to exist the way that you initially sketched it out, then perhaps lazy loading is actually a concept that is meaningful to the domain? In this case it lives in the domain and should probably have a more specific and meaningful name than simply LazyLoader.
Makes sense?
Are you hand writing your data access layer? If so, you may want to try the technique outlined here:
http://mynerditorium.blogspot.com/2010/01/practical-pi-lazy-loading-for-your-hand.html
Note that I am following more of a standard DAO pattern, but I think you could apply the lazy loading bits to your specific pattern.
When using the above technique, I attach the lazy loading collection to the aggregate in the aggregate's DAL. However, I would consider the collection to be a member of the domain layer.
精彩评论