Question

A fellow developer and I are conversing (to put it lightly) over Lazy-Loading of Properties of an object.

  • He says to use a static IoC lookup call for resolution and Lazy-Loading of objects of an object.
  • I say that violates SRP, and to use the owning Service to resolve that object.

So, how would you handle Lazy-Loading following IoC and SRP?

You cannot Unit test that lazy-loaded property. He rebuttles that one saying, "you already have unit tests for the UserStatsService - there's your code coverage." A valid point, but the property remains untested though for "complete" coverage.

Setup / code patterns:

  • Project is using strict Dependency Injection rules (injected in the ctors of all services, repositories, etc).
  • Project is using IoC by way of Castle (but could be anything, like Unity).

An example is below.

public class User
{
  public Guid UserId { get; set; }

  private UserStats _userStats;
  // lazy-loading of an object on an object
  public UserStats UserStats
  {
    get
    {
      if (_userStats == null)
      {
        // ComponentsLookup is just a wrapper around IoC 
        // Castle/Unity/etc.
        _userStats = 
          ComponentsLookup
            .Fetch<UserStatsService>()
              .GetByUserId(this.UserId);
      }
      return _userStats;
    }
  }
}

The above shows an example of lazy-loading an object. I say not to use this, and to access UserStatsService from the UI layer wherever you need that object.

EDIT: One answer below reminded me of the NHibernate trick to lazy-loading, which is to virtualize your property, allowing NHibernate to create an over-load of the lazy-loading itself. Slick, yes, but we are not using NHibernate.

No one really tackles the matter of Lazy-Loading. Some good articles and SO questions get close:

I do see a benefit of lazy-loading. Don't get my wrong, all I did was lazy-loading of my complex types and their sub-types until I switched to the D.I.-ways of the ninja. The benefit is in the UI layer, where a user's stats is displayed, say, in a list with 100 rows. But with DI, now you have to reference a few lines of code to get that user stats (to not violate SRP and not violate the law-of-Demeter), and it has to walk this long path of lookups 100+ times.

Yes yes, adding caching and ensuring the UserStatsService is coded to be used as a Singleton pattern greatly lower the performance cost.

But I am wondering if anyone else out there has a [stubborn] developer that just won't bend to the IoC and D.I. rules completely, and has valid performance/coding points to justify the work-arounds.

Was it helpful?

Solution

Entities themselves should not have the responsibility of lazy loading. That is an infrastructural concern whose solution will lie elsewhere.

Let's say an entity is used in two separate contexts. In the first, its children are used heavily and are eagerly-loaded. In the second, they are used rarely and are lazy-loaded. Is that also the entity's concern? What would the configuration look like?

NHibernate answers these questions by proxying the entity type. A property of type IList<Entity> is set by the infrastructure to an implementation which knows about lazy loading. The entity remains blissfully unaware. Parent references (like in your question) are also handled, requiring only a simple property.

Now that the concern is outside the entity, the infrastructure (ORM) is responsible for determining context and configuration (like eager/lazy loading).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top