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