Design patterns 每个实体一项服务?

Design patterns 每个实体一项服务?,design-patterns,architecture,domain-driven-design,Design Patterns,Architecture,Domain Driven Design,再次-我对DDD的事情感到困惑:) 我有一个architeture(我仍在开发中),简而言之,它是这样的: DataLayer: EntityDao -> Implementing domain layer interfaces (NHibernate) DomainLayer: EntityRepository -> Repository for each entity with injected Dao DomainObjects/Entitys -> Some lo

再次-我对DDD的事情感到困惑:)

我有一个architeture(我仍在开发中),简而言之,它是这样的:

DataLayer:
 EntityDao -> Implementing domain layer interfaces (NHibernate)
DomainLayer:
 EntityRepository -> Repository for each entity with injected Dao
 DomainObjects/Entitys -> Some logic
UI
 ASP.Net MVC
我现在正处于创建和使用某个服务类的阶段。我对此有一些疑问:

1.我是否应该为每个实体/域对象至少创建一个服务

2.a.服务是否应该有“查询”方法,如Find、FIndAll、FIndAll(LINQQuery)

2.b.我是否应该停止使用上层(UI)中的Repository来获取实体的集合(“查找”类方法),并开始只使用服务

3.如果对2个问题的回答是“否”-我是否应该以并行方式使用服务和存储库(在UI中,我只需要获取所有实体的信息,我使用Repository.FindAll,当我需要获取该实体的“逻辑”列表,我使用Service.FindXXX方法)

4.不知何故,我觉得Repository不适合域层—我是否应该以某种方式将它们分开,并在域中只保留特定于域的对象,如实体和服务?如果是-给我一些如何实现的结构示例

某些对象的示例:

道:

公共类NHibernateDao:IDao
{
公共NHibernateDao(){}
公共T获取(对象id)
{
T entity=(T)NHibernateSession.Get(entityType,id);
返回实体;
}
公共T加载(对象id)
{
T entity=(T)NHibernateSession.Load(entityType,id);
返回实体;
}
公共虚拟T更新(T实体)
{
NHibernateSession.Update(实体);
返回实体;
}
...
存储库:

public class BaseRepository<T>:IRepository<T>
{
    private DataInterfaces.IDao<T> mDao;

    public virtual T Get(object id)
    {
        return mDao.Get(id);
    }
    public virtual void Delete(T entity)
    {
        mDao.Delete(entity);
    }
    public virtual T Update(T entity)
    {
        return mDao.Update(entity);
    }
    public virtual IQueryable<T> FindAll()
    {
        return mDao.FindAll();
    }
    ...
公共类基存储库:IRepository
{
私有DataInterfaces.IDao mDao;
公共虚拟T获取(对象id)
{
返回mDao.Get(id);
}
公共虚拟作废删除(T实体)
{
删除(实体);
}
公共虚拟T更新(T实体)
{
返回mDao.Update(实体);
}
公共虚拟IQueryable FindAll()
{
返回mDao.FindAll();
}
...
域对象,目前主要是获取/设置容器-此问题的背景是删除该贫血模型。

我的想法:

  • 服务为业务逻辑提供上层接口。通常,您应该隐藏域级实现详细信息(较低)在其方法背后,基本上是命令或查询。一个好的思维方式可能是根据用例或用户故事命名您的服务方法。并且您不应该提供服务客户端(UI)所需的更多功能
  • 2a.如果您的UI需要来自某种类型实体的所有数据,那么是,否则否。FindAll()几乎不是一个用例

    2b.你应该从你的服务中使用存储库,这实际上是你唯一应该使用它的地方

    3见2b

    4是的。您应该为域中的存储库保留接口,但实现应该是在数据访问中。然后您可以用一些IoC容器粘合所有内容。可能是这样的:

    //在域中
    公共接口存储库{
    用户GetById(Guid id);
    }
    //在数据访问中
    公共类UserRepository:IUserRepository
    {
    public UserRepsitory(/*某些orm特定的依赖项*/){}
    公共用户GetById(Guid id){/*实现*/}
    }
    
    1.每个实体一项服务

    不需要。您不需要为一个实体创建一个服务。 在DDD中,您将为无法自然映射到单个实体(或值对象)的操作创建服务。良好的服务(来自):

    • 该操作涉及的域概念不是实体或值对象的自然部分
    • 接口是根据域的元素定义的
    • 该操作是无状态的
    因此,一个服务可以使用许多实体,并且可能有许多实体根本不被单个服务使用

    2a.服务是否应该有“查询”方法(…)

    不可以。一般来说,这些是存储库方法,不放在服务上。但是,服务上可能有返回实体集合的操作

    2b.我应该停止使用上层(UI)中的存储库来获取实体的集合(“查找”类方法)并开始只使用服务吗

    这可能是个好主意。通常,当应用程序在UI层中使用多个存储库时,UI会对多个实体执行域操作。这些操作通常应该在域层中实现;或者在实体本身中实现,或者在服务中实现

    3.我应该从UI并行使用服务和存储库吗

    最好不要这样做,请参见上文;尽管在某些情况下,您可以通过这样做快速创建部分UI

    4.不知怎的,我觉得Repositories不适合域层


    你是对的,你应该只把存储库接口放在域中。请看Kostassoid的回答,举个例子。

    那么你是说我应该删除DAO?好吧,基本上存储库和DAO是解决同一问题的不同模式,所以我会说是的,我无法想象你为什么需要另一个抽象层。至少这就是为什么根据我的经验。关于2a:我在视图帮助器和控制器中使用存储库,在这种情况下,正确的方法是在我的服务层中实现find方法?但这不会改变责任?我认为访问控制器或视图帮助器中的存储库只是为了获取数据是好的,不正确的方法是更改这些层中的数据。或者我错了?@JCM,我会更进一步,使用CQRS模式,这意味着不使用SL进行只读操作。在这种情况下,您可以将复杂的查询提取到一些抽象中,但我不会将其称为存储库,因为这有点误导。但是,如果您需要使用SL进行查询,那么通常最好使用定义某种DSL,用领域语言构造查询规范(如query.Users.WithRatingAbove(100).和.LivingIn(“US”).a
    public class BaseRepository<T>:IRepository<T>
    {
        private DataInterfaces.IDao<T> mDao;
    
        public virtual T Get(object id)
        {
            return mDao.Get(id);
        }
        public virtual void Delete(T entity)
        {
            mDao.Delete(entity);
        }
        public virtual T Update(T entity)
        {
            return mDao.Update(entity);
        }
        public virtual IQueryable<T> FindAll()
        {
            return mDao.FindAll();
        }
        ...