【问题标题】:Where to put business logic in DDD that shared between domain layer and presentation layer?领域层和表示层共享的 DDD 中的业务逻辑应该放在哪里?
【发布时间】:2023-03-26 08:25:01
【问题描述】:

我正在使用 DDD 模式开发应用程序。

我在域层中有Invoice 类。

public class Invoice
{
    List<InvoiceLine> list = new List<InvoiceLine>();

    public DateTime Date { get; set; }

    public Customer Customer { get; set; }

    public decimal GrandTotal 
    { 
        get
        {
            // Simplified grand total. 
            // It's actually include tax and discount to calculate.

            decimal total = 0m;
            foreach(InvoiceLine line in Lines)
                total += line.LineTotal;

            return total;
        }
    }

    public IEnumerable<InvoiceLine> Lines
    {
        get { return list; } 
    }

    public void AddLine(InvoiceLine line)
    {
        lines.Add(line);
    }
}

我正在使用 mvvm 模式,所以我也有一个视图模型来编辑发票。我的问题是我应该将业务逻辑放在哪里来计算 GrandTotal,以便域和表示上的业务逻辑相同?

我是否应该将代码从域复制到演示文稿(InvoiceInvoiceViewModel)?还是制作一个域和演示文稿都可以使用的服务?

【问题讨论】:

    标签: wpf mvvm domain-driven-design


    【解决方案1】:

    DDD 中聚合的主要目标是保持一致性 - 在您的情况下,一致性意味着例如 GrandTotal 将始终具有正确的值。也就是说,没有规则规定聚合类不能使用额外的类来获得这种一致性。

    例如,您可以提供一个类,其唯一职责是计算总计并在您的域和视图模型中使用它。我不会称它为服务,因为它与 DDD 概念无关。示例:

    public interface IInvoiceLine
    {
        decimal Amount {get;}
    }
    
    public interface ICalculateGrandTotal
    {
        decimal Calculate(IEnumerable<IInvoiceLine> lines);
    }
    
    public class GrandTotalCalculator: ICalculateGrandTotal
    {
        ...
    }
    

    现在您可以在视图模型和域中使用此计算器,而无需重复代码。除了接口之外,视图模型和域类之间没有直接耦合。 IInvoiceLine接口可以由视图模型和领域实体分别实现。

    【讨论】:

    • 这是一个很好的解决方案。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    • 2017-03-27
    • 2016-12-18
    • 2012-07-16
    • 2016-12-06
    • 2013-03-04
    • 1970-01-01
    相关资源
    最近更新 更多