DDD: Reconstituting objects from multiple Repositories

Now that our CustomerRepository can save customers as well as associated addresses in a decoupled manner we need to move onto the next problem, reconstituting our customer object with an address. As others have mentioned we may want to Lazy Load the address since there will be instances when it isn't needed.

public class Customer {
    public int addressKey;
    public Address Address {
       get {
         if(address == null) {
            address = new AddressRepository().Load(addressKey);
        }
         return address; 
       }
}

Ok, so the above would work but is it really what we want? Using the above method we introduce a coupling between our Customer class and the AddressRepository. I'd like to remove the coupling to allow us to support different address repositories as we can with the .Save within our CustomerRepository (via RepositoryFactory). I'd also like to remove any knowledge of repositories from my domain objects. Although it isn't always possible I prefer for application code to have knowledge of repositories NOT my domain objects. So how can we remove the coupling to the AddressRepository AND remove the Repository outright?

public class Customer {
     public int addressKey;
     public Address address; 
     public Address Address {
          get { return address; }
     }
}

One option is to have to separate methods on our CustomerRepository for returning Customer objects with and without Addresses loaded.

public class CustomerRepository : DomainRepository {
   public Customer Load(int customerKey) {
        Customer customer = RetrieveFromDataStore(customerKey);
        return customer;
   } 
 
   public Customer LoadWithAddress(int customerKey) {
       Customer customer = Load(customerKey);
       DomainRepository addressRepository = this.RepositoryFactory.GetRepository(typeof(Address));
       customer.Address = addressRepository.Load(customer.AddressKey); 
       return customer;
    }
}

The negative to the above is that we have two different methods for loading customers. If we use .Load() and then try and access the address property we get a null which could cause users of the class to think that the Customer doesn't have an address which is not the case. On the positive side using the above design forces the users of the class to think about how the customer is going to be used. Rather then lazy loading the address we have it pre-populated which ensures we don't run into performance problems due to users not realizing that the property is lazy loaded and causing additional hits to the database. What other options do we have? Perhaps introducing a proxy object could help?

public class Customer {
    public Address Address {
         get { return addressProxy.Address; }
    }

    protected internal AddressProxy AddressProxy {
        set { addressProxy = value; }
    }

public class AddressProxy {
   private int addressKey;
   private DomainRepository addressRepository; 
   private Address Address;

   public AddressProxy(int addresskey, DomainRepository addressRepository) {
      this.addressKey = addressKey;
      this.addressRepository = addressRepository;
    }
    public Address Address {
     get {
          if(address == null) {
             address = addressRepository.Load(addressKey);
          }
          return address;
      }

And our CustomerRepository Load methods change to:

public class CustomerRepository {
    public Customer Load(int customerKey) {
         Customer customer = Load(customerKey);
         DomainRepository addressRepository = this.RepositoryFactory.GetRepository(typeof(Address));
         customer.AddressProxy = new AddressProxy(customer.AddressKey, addressRepository);
         return customer;
     }
}

The negative's of this solution is that we're introducing the proxy class into the Customer which is a little messier then I'd like. It'd be nice if our AddressProxy could inherit from our Address and provide a nice way of handling the loading of itself so that the Customer didn't have to use the AddressProxy. We could have the proxy overload all the properties of the address but that would be pretty ugly for all but the simplest of classes. I'm still not real pleased with the solution that I came up with here but it's at least a start. Perhaps all of my wonderful readers can help improve the "design"?

# re: DDD: Reconstituting objects from multiple Repositories

Sunday, October 03, 2004 8:21 PM by Deyan Petrov    
I am using currently the Proxy pattern like this:

using System;

namespace Framework.ObjectHandling
{
public delegate object LoadObjectDelegate(int id);

/// <summary>
/// ObjectProxy is used for lazy-loading related objects/collections.
/// Domain objects explicitely use it as the type of their relations(1:1, 1:M, N:M).
/// </summary>
public class ObjectProxy
{
private int _key = 0;
private LoadObjectDelegate _loadObjectDelegate = null;

private object _object = null;

public ObjectProxy(int key, LoadObjectDelegate loadObjectDelegate)
{
_key = key;
_loadObjectDelegate = loadObjectDelegate;
}

public ObjectProxy(object obj)
{
_object = obj;
}

public ObjectProxy()
{
//empty
}

public int Key
{
get
{
return _key;
}
}

public object Object
{
get
{
if(_object == null && _loadObjectDelegate != null)
{
_object = _loadObjectDelegate(_key);
}

return _object;
}

set { _object = value; }
}
}
}

In the domain object I have:

public class User
{
//....
private ObjectProxy _country = new ObjectProxy(null); //Country
public Country Country
{
get
{
return _country.Object as Country;
}
}
//.....


}

When I load the object, i.e. in the data access layer, I use a special internal constructor with all persistent fields, which accepts the ObjectProxy and sets it. I instantiate an ObjectProxy just by passing it an id and a LoadObjectDelegate:
//....
ObjectProxy country = null;
if(dr["CountryID"] != DBNull.Value)
{
int countryID = (int)dr["CountryID"];
country = new ObjectProxy(countryID,
new LoadObjectDelegate(CountryDA.MaterializeProxy));
}
else
country = new ObjectProxy(null);
//...

Additionally you can use the DynamicProxy project from the .NET implementation of Avalon, which automatically creates inherited proxies.

Br,
Deyan

# re: DDD: Reconstituting objects from multiple Repositories

Sunday, October 03, 2004 10:38 PM by Steve    
Deyan, I like it! Much better then what I thought up as I was writing that post. I'll definitely have to check out the DynamicProxy project and see how I might be able to use it!

# I want to meet Steve Maine's associate too

Monday, October 04, 2004 3:30 AM by Steve Eichert    
I want to meet Steve Maine's associate too

# Interesting Topics on Domain Repositories

Monday, October 04, 2004 10:48 AM by Mike Lorengo's Weblog    
Interesting Topics on Domain Repositories

# re: DDD: Reconstituting objects from multiple Repositories

Tuesday, October 05, 2004 10:07 AM by Jimmy Nilsson    
Hi Steve,

Very nice reading. Here's my try of keeping the conversation going:
<a target="_new" href="http://www.jnsk.se/weblog/posts/dddstyle2.htm">http://www.jnsk.se/weblog/posts/dddstyle2.htm</a>

Best Regards,
Jimmy
www.jnsk.se/weblog/
###

# re: DDD: Reconstituting objects from multiple Repositories

Tuesday, October 05, 2004 11:13 AM by Sanin Saracevic    
Good stuff. I wrote about a possible way to go about lazy load here:

&lt;a href=&quot;<a target="_new" href="http://blogs.saninsaracevic.com/dotnet/archive/2004/09/07/343.aspx&quot;/&gt;">http://blogs.saninsaracevic.com/dotnet/archive/2004/09/07/343.aspx&quot;/&gt;</a>

# re: DDD: Reconstituting objects from multiple Repositories

Wednesday, October 06, 2004 7:39 AM by Sanin Saracevic    
More comments in my blog:
<a target="_new" href="http://blogs.saninsaracevic.com/dotnet/archive/2004/10/06/373.aspx">http://blogs.saninsaracevic.com/dotnet/archive/2004/10/06/373.aspx</a>

# re: DDD: Reconstituting objects from multiple Repositories

Thursday, December 14, 2006 7:25 AM by JupiterMoon    
How about using dependancy injection? We have a similar problem where we have a ditributed data set across multiple systems. To solve it we do the following:

Repository
{
ICustomer GetCustomer(name)
{
foreach(CustomerRespository r in CustomerRepositories)
{
if(r.HasCustomer(name))
{
return r.GetCustomer();
}
}

throw new NotFoundExc();
}
}

CustomerRespository
{
ICustomer GetCustomer(name)
{
return new Customer(this);
}
}

Customer
{
readonly ICustomerRespository repository
#(ICustomerRespository)
{
this.repository = ICustomerRespository;
}
}

That way the repository is responsible for telling the customer who it should talk to and the Customer() object walks around with the correct repository for it's lifetime.

# re: DDD: Reconstituting objects from multiple Repositories

Friday, February 15, 2008 11:17 AM by Fuzzy    
Ummm. new to all this .. so why can't we just do ...
...
Customer customer = RetrieveFromDataStore(customerKey);
customer.Address = new AddressRepository().Getfor (customer.Id);

return customer;

In the Load Customer call ???

Post a Comment

 
 
Prove you're not a spammer: 
0 + 1 =