DDD 中的数据实体、领域实体和存储库

Data Entities, Domain entities and the Repositories in DDD

我正试图了解 DDD,但我被卡住了。 这就是我设置项目的方式:

Data Access Layer
 -Entity models that map to the db
 -Db connection stuff
 -Repositories implementations

Domain Layer
 -Models that represent the DAL entity models
 -Repositories interfaces

Application Layer
 -MVC application that uses Domain models

我在这里看到的第一个问题是域模型与实体模型完全相同,我对此有一个严重的问题:实体模型显然配置了验证,比如 "max length"、"nullable"、"required" 等。现在,为了符合我所理解的 DDD,除了 DAL,我不能在任何地方直接使用这些模型,所以我创建了我的领域层。在域层,我为 UI 验证复制了所有这些验证规则,更糟糕的是,如果我需要更改规则,我将不得不在两个地方更改它:DAL 和域.

示例:

User Entity in DAL
Name (required)
Last name (required)
Email (required, maxlen 120)
Username (required, maxlen 120)

User Domain Model
Name (required)
Last name (required)
Email (required, maxlen 120)
Username (required, maxlen 120)

我觉得很奇怪的另一件事是这个架构中的存储库组织。 按照我阅读的内容,我创建了一个 GenericRepository 接口和一个继承了 GenericRepository 的 UserRepository 接口,它们都在 Domain 层中。 我在 DAL 中实现了 GenericRepository,该实现为用于创建存储库的实体类型创建了一个 DAO。到目前为止,还不错。

然后,我着手实现了UserRepository,这里又遇到了一个问题:UserRepository 接口需要Domain User 模型,当我尝试在DAL 中实现该接口时,我需要使用Domain 来实现它用户模型,这导致为域模型而不是 DAL 模型创建 DAO,这没有任何意义。唯一的解决方法是在域层中引用 DAL,这是错误的。

Domain Layer:

public interface IGenericRepository<TEntity>
{
    TEntity FindById(TKey id);
}

public interface IUserRepository : IGenericRepository<Domain.User>
{
    Task<User> FindByUserNameAsync(string userName);
}


DAL:

public abstract class GenericRepository<TEntity> : IGenericRepository<TEntity>
{
    protected DbContext ctx;
    protected DbSet<Entity> dbSet;

    public GenericRepository(DbContext context)
    {
        ctx = context;
        dbSet = ctx.Set<TEntity>();
    }

    public virtual TEntity FindById(TKey id)
    {
        return dbSet.Find(id);
    }
}

 public class UserRepository : GenericRepository<Domain.Models.User>, IUserRepository
{
    public UserRepository(DbContext context)
        : base(context)
    {
       // THIS WILL CREATE A DAO FOR A DOMAIN MODEL
    }

    // rest of code...
}

任何人都可以阐明我在 DDD 中遗漏了什么吗?

你的问题和你对 DDD 的怀疑是有道理的,因为你是从 code-point-of-view 接近这个主题的。

您似乎停滞不前 "code duplication" 而您即将错过大局。

来自wikipedia定义:

Domain-driven design (DDD) is an approach to software development for complex needs by connecting the implementation to an evolving model. The premise of domain-driven design is the following:
- placing the project's primary focus on the core domain and domain logic
- basing complex designs on a model of the domain
- initiating a creative collaboration between technical and domain experts to iteratively refine a conceptual model that addresses particular domain problems.

如果您的模型唯一需要的业务逻辑是字符串字段的验证,那么您可能需要 DDD 以外的其他方法来开发您的应用程序。

如何看待 DDD: DDD 是一种开发哲学(由 Eric Evans 定义),专注于为复杂领域编写软件的开发团队。这些团队需要明确的界限,因为一个变化,即进入一个模型,不应该影响另一个团队的模型、进度等(因此你有你的代码重复)。

如何不去想DDD: 它不是具有预定义代码适用模式的框架。

团队开始 DDD 的常见问题:

  • 过分强调战术模式的重要性: 与其解决真正的业务问题,不如关注聚合根、值对象等。
  • 关注代码而不是 DDD 的原则:代码应该是 DDD 过程的最后一次迭代。真正的工作是理解业务问题并尝试找到一个简单易懂的解决方案(去掉问题的复杂性)。

您可以在 Patterns, Principles, and Practices of Domain-Driven Design 中找到更多陷阱以及如何学习应用 DDD 的建议 (陷阱的例子取自本书第9章)