OOP App Architecture: Which layer does a lazy load

2019-07-10 03:50发布

问题:

I am planning the 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

回答1:

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?



回答2:

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.