Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 域对象应该由聚合中的事件处理程序创建吗_Ruby_Domain Driven Design_Cqrs_Event Sourcing_Rails Event Store - Fatal编程技术网

Ruby 域对象应该由聚合中的事件处理程序创建吗

Ruby 域对象应该由聚合中的事件处理程序创建吗,ruby,domain-driven-design,cqrs,event-sourcing,rails-event-store,Ruby,Domain Driven Design,Cqrs,Event Sourcing,Rails Event Store,当我们在聚合上调用域操作时,我们传递一些原语/域对象,我们验证一些业务规则,并在最后应用域事件。当我们最后应用事件时,我们更新对象的状态。在最后的步骤中,我们必须创建对象或从存储库加载对象。这对我来说似乎很难或是错误的,因为有很多重复的任务 以下是一个例子: 域操作 应用事件 正如您在上面的代码中所看到的,我必须构建事件数据build\u create\u event\u data,它将域对象转换为事件的基本体(因为建议将基本体放入事件中)。然后,当我必须应用该事件时,我必须再次创建对象。是我做

当我们在聚合上调用域操作时,我们传递一些原语/域对象,我们验证一些业务规则,并在最后应用域事件。当我们最后应用事件时,我们更新对象的状态。在最后的步骤中,我们必须创建对象或从存储库加载对象。这对我来说似乎很难或是错误的,因为有很多重复的任务

以下是一个例子:

域操作 应用事件 正如您在上面的代码中所看到的,我必须构建事件数据
build\u create\u event\u data
,它将域对象转换为事件的基本体(因为建议将基本体放入事件中)。然后,当我必须应用该事件时,我必须再次创建对象。是我做错了还是缺少了什么


这里最好的方法应该是什么?

我将从一些领域的想法开始重新考虑。 在
def create
中创建的
合同对我来说似乎是另一个聚合。
若我要为那个域定义一个域模型,我不会在这里创建它,我只会将contract作为参数传递给create方法。这将是
ProjectManagementDomain::Contract
而不是
Contracts::Contract
(这表明Contract是另一个子域的一部分)。顺便说一句,
客户
合同人
部门
。。。等等)

另一件事是,对我来说,这个方法&这个域事件处理了太多的数据。我更喜欢具有更具体业务操作的更细粒度的域事件。这里应用的好的启发方法是只处理一起变化的数据。除非您使用Jira(*用您讨厌的另一个工具替换Jira)集成构建项目管理域,否则这可以建模为一组操作,并作为域事件的结果发布。也就是说,您能否创建一个没有定义日期的项目?您是否可以在没有指定客户/经理/部门/联系人的情况下创建项目

建议在事件中放置原语

嗯。这是正确的。但您仍然可以在此处传递域对象,尤其是值对象。对我来说,唯一的限制是它们必须序列化为基本类型,并且这里使用的对象必须在同一个有界上下文的范围内。此外,我永远不会在域事件中发布被其他有界上下文使用的对象(避免耦合)

这么快;博士:

  • 重新思考您的域模型
  • 保持你的体积小
  • 而您的事件甚至更小(尤其是用于聚合的事件源的事件,您可以在有界上下文之外发送数据时使用摘要事件模式)

首先,我想重新考虑一下这个领域的一些想法。 在
def create
中创建的
合同对我来说似乎是另一个聚合。
若我要为那个域定义一个域模型,我不会在这里创建它,我只会将contract作为参数传递给create方法。这将是
ProjectManagementDomain::Contract
而不是
Contracts::Contract
(这表明Contract是另一个子域的一部分)。顺便说一句,
客户
合同人
部门
。。。等等)

另一件事是,对我来说,这个方法&这个域事件处理了太多的数据。我更喜欢具有更具体业务操作的更细粒度的域事件。这里应用的好的启发方法是只处理一起变化的数据。除非您使用Jira(*用您讨厌的另一个工具替换Jira)集成构建项目管理域,否则这可以建模为一组操作,并作为域事件的结果发布。也就是说,您能否创建一个没有定义日期的项目?您是否可以在没有指定客户/经理/部门/联系人的情况下创建项目

建议在事件中放置原语

嗯。这是正确的。但您仍然可以在此处传递域对象,尤其是值对象。对我来说,唯一的限制是它们必须序列化为基本类型,并且这里使用的对象必须在同一个有界上下文的范围内。此外,我永远不会在域事件中发布被其他有界上下文使用的对象(避免耦合)

这么快;博士:

  • 重新思考您的域模型
  • 保持你的体积小
  • 而您的事件甚至更小(尤其是用于聚合的事件源的事件,您可以在有界上下文之外发送数据时使用摘要事件模式)
def create(uuid:, name:, description:, start_date:, end_date:, customer:, contact_person: , type: , manager:,
           department:, author:)
  result = Contracts::CreateContract.new(object: self).call(start_date: start_date, end_date: end_date)
  raise Exceptions::DomainError.new(payload: result) if result.errors.present?
  data = build_creat_event_data(uuid: uuid,
                           name: name,
                           description: description,
                           start_date: start_date,
                           end_date: end_date,
                           customer: customer,
                           contact_person: contact_person,
                           type: type,
                           manager: manager,
                           department: department,
                           author: author)
  apply(ProjectManagementDomain::Events::ProjectCreated.strict(data: data))
end
def apply_project_created(event)
      @uuid = event.data[:uuid]
      @name = event.data[:name]
      @description = event.data[:description]
      @status = STATUSES.dig(:draft)
      @type = ProjectType.new(event.data[:type])
      @start_date = event.data[:start_date]
      @end_date = event.data[:end_date]
      @customer = Customer.new(event.data[:customer])
      @manager = Manager.new(event.data[:manager])
      @department = Department.new(event.data[:department])
      @contact_person = ContactPerson.new(event.data[:contact_person])
      @legacy_id = event.data[:legacy_id]
    end