Search code examples
phpdomain-driven-designlazy-loadingpoeaa

OOP App Architecture: Which layer does a lazy loader sit in?


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

Solution

  • 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?