控制反转,依赖注入w / SRP和延迟加载

时间:2010-01-12 00:34:04

标签: inversion-of-control lazy-loading single-responsibility-principle

一位开发人员和我正在交谈(轻描淡写)对象的属性的Lazy-Loading。

  • 他说要使用静态IoC查找调用来解析和延迟加载对象的对象。
  • 我说违反了SRP,并使用拥有的服务来解析该对象。

那么,您将如何处理IoC和SRP之后的Lazy-Loading?

你不能单元测试延迟加载的属性。他重申那句话说:“你已经为UserStatsService进行了单元测试 - 这是你的代码覆盖率。”这是一个有效的观点,但是对于“完整”的覆盖范围,该属性仍未经过测试。

设置/代码模式:

  • 项目使用严格的依赖注入规则(注入所有服务,存储库等)。
  • Project正在通过Castle使用IoC(但可能是Unity之类的任何东西)。

以下是一个例子。

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;
    }
  }
}

以上显示了延迟加载对象的示例。我说不要使用它,并从UI层访问任何需要该对象的UserStatsService。

编辑:下面的一个答案让我想起了延迟加载的NHibernate技巧,即虚拟化你的属性,允许NHibernate创建一个懒惰加载本身的过载。光滑,是的,但我们没有使用NHibernate。

没有人真正解决Lazy-Loading的问题。一些好文章和SO问题接近:

我确实看到了延迟加载的好处。不要弄错我,我所做的只是懒惰加载我的复杂类型及其子类型,直到我切换到忍者的D.I.-方式。好处在于UI层,其中用户的统计数据显示在具有100行的列表中。但是使用DI,现在你必须引用几行代码来获取用户统计信息(不违反SRP并且不违反Demeter法则),并且必须走这条长路径的查找次数100次。 / p>

是的,添加缓存并确保对UserStatsService进行编码以用作Singleton模式,从而大大降低了性能成本。

但是我想知道是否有其他人有一个[顽固]开发人员不会屈服于IoC和D.I.完全规则,并具有有效的性能/编码点来证明解决方法的合理性。

1 个答案:

答案 0 :(得分:5)

实体本身不应该负责延迟加载。这是一个基础设施问题,其解决方案将在其他地方。

假设一个实体在两个不同的上下文中使用。首先,它的孩子们被大量使用并且急切地负担。在第二种情况下,它们很少使用并且是懒惰的。这也是实体关注的问题吗?配置会是什么样的?

NHibernate通过代理实体类型来回答这些问题。属性IList<Entity>的属性由基础结构设置为知道延迟加载的实现。该实体仍然没有意识到。也会处理父引用(如您的问题),只需要一个简单的属性。

现在关注点在实体之外,基础架构(ORM)负责确定上下文和配置(如急切/延迟加载)。