在EventSourcing中将业务逻辑应用于何处

如何解决在EventSourcing中将业务逻辑应用于何处

在事件外包中,我对于到底必须在何处应用业务逻辑感到困惑。我已经在Google中进行了搜索,但是所有示例都是非常基本的,即从事件对象更新Handler中对象的状态,但是在我的另一种情况下,对于到底应该在何处应用业务逻辑,有些困惑不明白。 >

例如:例如,让一个场景更新 IntervieweeVO 的状态,该状态位于 Interview聚合类中,如下所示:

class Interview extends AggregateRoot {

  private IntervieweeVO IntervieweeVO;

}

class IntervieweeVO {
  int performance;
  String status;
}

class IntervieweeSelectedEvent extends BaseEvent {
  private IntervieweeVO IntervieweeVO;
}

我有一个业务逻辑,即,如果受访者的表现

所以,我的疑问是:我应该在哪里保持业务逻辑?以下是 3种情况

1)在应用事件之前:做业务逻辑,然后应用(IntervieweeSelectedEvent),然后应用eventstore.save(intervieweeSelectedEvent)

2)在EventHandler内部:在EventHandler类中应用业务逻辑,例如handle(IntervieweeSelectedEvent受访者SelectedEvent),检查业务逻辑,然后更新ReadModel表中的对象状态。

3)在两个地方都应用业务逻辑,即在应用事件之前和处理事件时(结合1​​ + 2)

请在上面澄清我。

解决方法

事件源的主要问题是很难使用综合场景来产生可行的示例。

但我可能会提出一些比采访更好的建议。如果比较计算机前时代基于事件的系统,您会发现一个事件流是组成某个实体生命周期的事件存储,这是一件很长的事情。实体中的事件可能跨越几天(一个跟踪某些文档流的列表),一年(某个组织的会计期)或数十年(某个人的病历)的事件。

单个事件流通常代表一个实体-法律程序,分类帐或个人...每个事件都是对实体状态的交易性更改(如ACID)。

在您的情况下,这样的实体可以是职位。公开,宣布,受邀者邀请,接受邀请,评估技能,提出要约,接受要约,关闭职位。从我的头顶上。

将事件添加到实体时,表示实体的状态已更改。这是关于实体的新真理。您要注意更改真相。因此,这就是业务逻辑发生的地方。您运行一些业务逻辑来决定是否更改真相的决定。您决定更新真相的状态-保存事件。话虽如此,在这种情况下,“被访者被拒绝”是有效的事件。

由于事件持续存在,因此实体中所有保存的事件按照其各自的顺序无条件地成为有关实体真相的部分。然后,您不必决定是“接受”还是“拒绝”持续的事件,而仅决定其如何影响投影。

,

您标记了问题cqrs,但这实际上是示例中缺少的部分。

事件外包仅仅是一种查看对象当前状态的方法。您可以将该状态保存为现在显示的状态,或者从发生的一切中获取状态。 (例如,银行帐户当前的余额为所有交易的金额或总和)

因此,事件是发生的事情的“事实”。在您的情况下,那将是具有一定分数的面试。而且(取决于您的业务逻辑),如果障碍会随着时间而改变,它也可以声明状态。

关键点在于,您应始终遵循以下链条:

“命令被验证,如果通过则创建持久的不可更改事件”

这意味着在您的情况下,我将选择选项1。应验证SelectIntervieweeCommand,如果一切正常,请创建一个IntervieweeSelectedEvent,这是不可更改的事实。因此,无论受访者是否通过了业务逻辑,都必须驻留在命令处理程序函数中。

,

您应该能够从事件流中重建特定时间点的实体状态。

这意味着应用事件不应包含状态映射逻辑以外的任何逻辑。在这些事件中必须明确定义从事件中预测AR状态所需的所有状态。

事件是一种定义状态更改的表达方式,而不是操作/命令。例如,如果IntervieweeRejected的意思是IntervieweeStatusChanged(rejected),则含义永远不会改变。 IntervieweeRejected事件不能暗示除status = rejected以外的任何事物,除非事件数据中捕获了其他状态(例如原因)。

很显然,状态的表示方式总是可以改变的,但是含义不能改变。例如,AR可能仅通过投影当前状态开始,然后在投影整个状态历史记录时开始。

apply(IntervieweeRejected) => status = REJECTED //at first
apply(IntervieweeRejected) => statusHistory.add(REJECTED) //later

我有一个业务逻辑,即如果受访者的绩效

业务逻辑将放置在标准的公共AR方法中。在这种特定情况下,您可能期望interviewee.assessPerformance(POOR)产生IntervieweePerformanceAssessed(POOR)IntervieweeRejected事件。如果您以后需要重新评估该智能筛选政策(例如,如果已更改),则可以实施reevaluateSmartScreeningPolicy操作。

此外,请注意,此类逻辑甚至可能不属于Interviewee AR本身。智能筛选策略可能被视为在IntervieweePerformanceAssessed事件之后/响应事件发生的事件。此外,我可以轻松地看到由AI驱动的智能筛选策略如何变得非常复杂,可以证明它生活在专用的Screening受限环境中。

您的问题实际上使我考虑了如何有效地捕获上下文或事件发生的原因,我已经问过here:)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-