首页 > 解决方案 > 如何设计聚合的领域驱动设计应用服务?

问题描述

我是域驱动设计的新手,所以我想询问有关使用聚合根的应用程序服务的问题。

我有一个聚合根。

public class Product: AggreagateRoot{
    publis int Id {get; set;}
    publis string Name {get; set;}

    public ICollection<Comment> Comments {get; set;}
    public ICollection<Types> Types {get; set;}
}

评论和类型与产品相关。因此,评论或类型本身并不意味着任何东西。

所以我正在为产品创建一个应用程序服务。

public class ProductService {

    public Product Create(ProductCommand command){
        .....
        ...
    }

    public Product Update(ProductCommand command){
        .....
        ...
    }

}

我应该像下面这样在 ProductService 中添加创建和更新评论和类型的方法吗?

public class ProductService {

    public Product Create(ProductCommand command){
        .....
        ...
    }

    public Product Update(ProductCommand command){
        .....
        ...
    }

    public Comment Create(CommantCommand command){
        var product = _context.Product.Find(command.ProductId);

        product.Comments.add(new Comment(command.message));

        _context.SaveChanges();
        .....
        ...
    }

    public Comment Update(CommantCommand command){
        var comment = _context.Comments.Find(command.Id);

        comment.message = command.message;

        _context.SaveChanges();
        .....
        ...
    }       
}

或者我应该为评论和类型创建单独的服务吗?

标签: design-patternsarchitecturedomain-driven-design

解决方案


public class Product: AggreagateRoot{
    public int Id {get; set;}
    public string Name {get; set;}

    public ICollection<Comment> Comments {get; set;}
    public ICollection<Types> Types {get; set;}
}

如图所示,这种模式通常被称为贫血域模型,通常被认为是一种反模式。缺少的部分是行为,即描述此数据结构如何随时间演变的逻辑,存在于您的应用程序服务代码中,而不是存在于域模型中。

换句话说,你在这里实现的是一个愚蠢的数据包。

我们通常做的是编写代码,以便域行为在域实体中。应用层中的代码只是调用领域模型代码。例如:

Create(CommantCommand command){
    var product = _context.Product.Find(command.ProductId);

    product.AddComment(command.message));

    _context.SaveChanges();
    .....
    ...

我应该为评论和类型创建单独的服务吗?

应用程序组件应该只与聚合根对话。这是扎根的一部分。因此,如果我们假设 Comments 和 Types 属于一个聚合,那么不,不应该为它们提供单独的服务。

如果多个产品共享同一个Type,那么将 Type 设为自己的聚合可能是有意义的。


推荐阅读