【问题标题】:Logic place in Domain Driven Design领域驱动设计中的逻辑位置
【发布时间】:2023-04-05 06:21:02
【问题描述】:

我阅读了很多有关 DDD 的信息,但我不知道如何在现实生活中使用它。我为我无法理解的事情做了一些示例(使用 C# 和实体框架)。

  1. 为用户加钱。用户只有金额。

好的,很简单。这是模型User的示例

class User
{
    public decimal Balance {get; private set; }

    public void AddMoney(decimal sum)
    {
        if(sum>0)
           Balance+=sum;
    }
}

但是我该如何使用它呢?

  1. 从数据库中获取用户
  2. 更新用户 - 由域模型执行
  3. 保存更改

那么,第一个问题是我应该在哪里执行从数据库(存储库)中获取和保存数据?我无法在我的域模型中执行此操作。

  1. 用户有交易历史,而不仅仅是简单的总和
class User
{
    public ICollection<Transaction> Transactions {get; private set; }

    public void AddMoney(decimal sum)
    {
        if(sum>0)
            Transactions.Add(new Transaction(sum));
    }
}

在这种情况下,我应该从数据库中获取用户,然后 EF 会将新实体添加到集合中。但它不是有效的,更有效的是做这样的事情:

transactionsRepository.Add(new Transaction(sum, userId)); 

但这不是 DDD 方式。

  1. 从一位用户那里获得资金并转移给另一位用户

在这种情况下,操作会影响多个模型。 我应该把适用于多个模型的逻辑放在哪里?(也许这个例子不够好)。

  1. 获取用户当前余额

用户的余额是所有交易的总和

decimal Balance() => transactionsRepository.Get().Sum(x=>x.TransactionSum);

在这种情况下,查询包含逻辑 - 我应该如何获取数据来做某事,而不是像其他示例中那样简单的 fetch\save 实体。 我应该在哪里放置逻辑查询?获取总余额,获取最后未读消息等。

【问题讨论】:

  • 如果没有要检查所有事务的不变量,则没有理由在聚合中保存事务集合。事务可以通过它自己的存储库成为它自己的聚合:Transaction t = user.AddMoney(sum); transactionRepo.Add(t); 将是完全有效的。
  • 请注意,会计不是这样运作的......

标签: c# entity-framework domain-driven-design


【解决方案1】:

那么,第一个问题是我应该在哪里执行从数据库(存储库)中获取和保存数据?我无法在我的域模型中执行此操作。

您可以在 Layered architecture 中的 Application serviceCQRS architecture 中的命令处理程序中执行此操作。

但这并不高效,更高效的是做这样的事情

它更有效,但确实不是 DDD 方式。聚合不应依赖于存储库。它们仅适用于存储在内存中的状态。应用服务负责加载和存储聚合。

我应该把适用于多个模型的逻辑放在哪里?

在 Sagas/流程管理器中。

我应该在哪里放置逻辑查询?

这取决于你查询什么。

如果不使用 CQRS:

如果您在聚合的方法中从聚合中查询数据。

如果您查询特定的聚合列表,您可以将该逻辑放入存储库中。

如果使用 CQRS,则任何查询都在读取模型/投影上完成。

【讨论】:

    猜你喜欢
    • 2011-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-06
    • 2011-01-04
    • 1970-01-01
    • 2015-12-13
    相关资源
    最近更新 更多