如果没有域驱动设计,存储库是否有用?

时间:2011-03-09 18:54:15

标签: c# asp.net nhibernate entity-framework domain-driven-design

假设我的应用程序不能保证完整的DDD设置,那么存储库是否仍然有用?我喜欢他们屏蔽下面的实现细节(例如使用实体框架)的方式。然而,根据定义,存储库往往与Aggregate Roots(这个概念仍然是我的圣杯)联系在一起。

我想这个问题也可以这样说:如果我有一个典型的3层应用程序,其业务层外观由基于功能的“逻辑分组”类组成(而不是像DDD中的聚合根),例如TradingManager和ContactsManager,创建“逻辑分组”存储库是否有意义。或者也许是数据访问对象,我认为它就像没有聚合根要求的存储库。当然,我仍然会有一个模型(EF POCO),它将在各层之间上下传递。

此外,我刚才描述的是否会被视为交易脚本方法?它肯定不是DDD,而不是Active Record。我甚至不确定EF4是否存在Active Record与Nhibernate一样。

我试图了解其他人在不遵循DDD时如何构建n层应用程序。

2 个答案:

答案 0 :(得分:5)

正如你所暗示的那样,听起来你更喜欢DAO。我认为DAO在非DDD项目中非常有用,你想要完全抽象出数据层技术。

就事务脚本而言,它与您的数据层设计正交。事务脚本意味着每个业务操作都被分组为一个过程调用。示例:事务脚本模式通常用于服务器端的WCF服务调用,每个服务方法都遵循事务脚本模式。可以这样想:使用事务脚本,实际的业务逻辑不在对象中,而是在事务脚本过程调用中直接写入。通用业务逻辑可以在事务脚本之间共享,但通常通过静态方法,帮助程序等来完成,而不是通过“纯”OO。

这里有一些伪代码

// traditional transaction script
public class MailService
{
    public void UpdateEmail(string userName, string newEmail)()
    {
       if(db.UserExists(userName))
       {
          if(EmailHelper.ValidateEmailFormat(newEmail))
          {
             db.UpdateEmail(userName, newEmail);
          }
       } 
    }
}

// transaction script with anemic domain objects
public class MailService
{
    public void UpdateEmail(string userName, string newEmail)()
    {
       var userDAO = new UserDAO();
       var emailDAO = new EmailDAO();

       var existingUser = userDAO.GetUserByName(userName);       

       if(existingUser != null)
       {
          if(EmailHelper.ValidateEmailFormat(newEmail))
          {
             emailDAO.UpdateEmail(existingUser, newEmail);
          }
       } 
    }
}  

// More of an OO / DDDish approach
public class MailService
{
    public void UpdateEmail(string userName, string newEmail)()
    {
       var userRepository = new Repository<User>();

       var userToUpdate = userRepository.Where(x => x.UserName = userName).FirstOrDefault();

       if(userToUpdate != null)
       {
           userToUpdate.Email = newEmail;

           if (user.IsValid())
           {
               userRepository.Update(userToUpdate);
           } 
       }
    }
}

显然,第一个例子根本不是OO。第二个示例比OO更基于对象,因为所有业务逻辑都发生在MailService调用中。第三个例子是传统的OO。服务呼叫中只发生控制流;所有业务逻辑都在User.IsValid()方法中处理。

这一切归结为您放置业务逻辑的位置。

答案 1 :(得分:1)

一如既往......“这取决于”。 :D抱歉......

我认为这归结为单一责任原则。如果你所有的DAO都在检索实体(好吧,做CRUD,而不是一个DbContext),没有别的......那么是的,滚动一个。如果你开始发现你有不同实体的自定义逻辑,那么你会想要考虑像存储库这样的东西。