DDD 聚合根 使用静态方法创建对象是否正确

Tan*_*Tan 4 c# domain-driven-design aggregateroot

像这样的 Create 方法是否正确?或者我应该在服务内创建用户。这是否破坏了 DDD 概念?

对于这种情况,最佳做法是什么?

注意:我也使用 DI。

  public class User : HistoryBase, IAggregateRoot
    {
        private IEnumerable<Role> _roles = new List<Role>();
        public string Name { get; protected set; }
        public string Lastname { get; protected set; }
        public string Email { get; protected set; }
        public string Password { get; protected set; }
        public string EmployeeNumber { get; protected set; }
        public bool Active { get; protected set; }
        public int SiteID { get; protected set; }
        public IEnumerable<Role> Roles { get { return _roles; } }

        public static User Create(string name, string lastname, string email, string password, string employeeNumber, Site site)
        {
            var user = new User()
            {
                Name = name,
                Lastname = lastname,
                Email = email,
                Password = password,
                EmployeeNumber = employeeNumber,
                SiteID = site.ID
            };

            return user;
        }
    }
Run Code Online (Sandbox Code Playgroud)

Fre*_*ver 5

DDD 主要是关于类及其属性的命名,以便它们准确地表达您的软件应该代表的业务领域的部分。

它实际上并没有规定任何技术实现细节,例如事物如何实例化。关键是类的属性和方法在域中有意义。

从域的角度来看,静态.Create()方法没有意义,但new ..()对构造函数的调用也没有意义。

您可以决定域实体/聚合的构造方法应Class.Create()改为new Class()

这不是“错误”

例如,如果您使用的框架/库需要公共无参数默认构造函数(常见于 EntityFramework 和一些序列化库),并且您希望实例化的“标准”方法明确(只能使用所有需要的参数进行调用) ),这是实现这一目标的完全有效的方法。

只要保持一致即可

如果您这样做,您应该为所有实体/聚合执行此操作。它成为一种约定,并将被记录为技术实现细节(就像默认情况下的构造函数一样)。

使用 CommandHandler,而不是服务(或工厂)

服务并不是真正用于实例化类(这就是工厂的用途)。

但是,您的代码似乎暗示您还在应用 EventSourcing 或其某些变体。假设您随后也在执行 CQRS,那么您的Create命令将在 CommandHandlers 方法中结束Create。如果需要的话,您可以在其中放置验证逻辑之类的东西。

所以那些 CommandHandlers 已经是你的工厂了,你不需要额外的层。

最后:

使用这样的静态实例化方法通常用于实现某种 Fluent API,例如使用 Builder 模式。它为链接调用提供语法糖。

因此,它可能会给其他开发人员/消费者留下调用可以链接的错误印象(在您的示例中不能链接)。

您可能仍然想定义默认的公共构造函数,这样您就可以有一个文档注释来不使用该构造函数,并有一个.Create()应该用作构造函数的文档注释。

考虑到所有这些因素,它仍然比仅使用构造函数更好吗?然后一定要这样做。据我所知,它不会影响“DDD-ness”。