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

edu*_*911 3 lazy-loading single-responsibility-principle inversion-of-control

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

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

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

你不能单元测试那个延迟加载的属性.他重申那句话说:"你已经为UserStatsService进行了单元测试 - 这是你的代码覆盖率." 有效点,但该物业仍然未经测试,但"完整"覆盖.

设置/代码模式:

  • 项目使用严格的依赖注入规则(注入所有服务,存储库等的ctors).
  • 项目通过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;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

是的,添加缓存并确保编写UserStatsService以用作Singleton模式,从而大大降低性能成本.

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

Bry*_*tts 5

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

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

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

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