设计模式 – 使用REST API的CQRS组件角色和职责

前端之家收集整理的这篇文章主要介绍了设计模式 – 使用REST API的CQRS组件角色和职责前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
关于带有DDD的CQRS以及构成每个组件的内容,有很多意见.我还没有开始研究事件采购,所以下面的列表不包含与此相关的任何内容.虽然对ES的深入了解会很有趣.

到目前为止,我有以下相关责任的组件(见下文).我在下面的几点中概述了一些问题.

REST端点/应用程序

>接收来自用户/ ui / etc的请求
>构建和发送相关命令
>如果命令需要来自其他有界上下文的值,则执行正确实例化命令所需的相关Finder调用(例如,Order需要用户ID)
>在GET的情况下:调用相关的Finder
> Finder坐在应用程序的这个级别.有界上下文写入方(命令处理程序,聚合,工厂,域服务等)不应该调用Finders.这将保持封装并通过仅将所需数据(而不是完整的DTO)传递给命令,它将成为适度的反腐败层.
>例如:

AggregateId orderId = AggregateId.get();
AggregateId userId = finder.findUserAggregateIdByEmail(email);
dispatcher.fire(new CreateOrderCommand(orderId,userId,orderItems));

命令

>通过调度命令对域进行更改
>命令是不可变的,包含有界上下文改变它的状态或抛出异常所必需的数据
>可以在创建对象时验证命令输入,以避免发送无效命令
>例如:new CreateOrderCommand(orderId,orderItems);

命令处理程序

>处理程序可以成功应用命令或引发异常
>每个命令只能有一个命令处理程序
>处理程序将加载或创建聚合根(存储库或聚合工厂)
>处理程序将命令应用于聚合根
>处理程序处理存储库
>不应该触发命令(在其有界的上下文中)
>命令处理程序是否应该调度事件?例如,成功保存到数据库后?或者这仅仅是Aggregate的责任?

聚合工厂

>封装正确初始化聚合根所需的逻辑
>工厂可以访问存储库
>工厂应该访问域名服务吗?
>例如:factory.createOrder(orderId,orderItems);

聚合根/聚合

>包含域逻辑,状态和行为
>负责派遣活动
> Aggregate Root封装了对Aggregates的访问
> Aggregate Root应具有唯一标识它的ID
>不应与外部服务(事件发布者除外)交互
>例如:order.cancel();

域名服务

>这包含不太适合聚合根的内容
>域服务可以与哪些组件进行交互?
>域服务是否应该触发命令/事件?
>例如:不确定在这里使用什么,上面的第一点充其量是模糊的.大多数行为很好地存在于Aggregate中,或者可以通过Sagas / Events / Commands实现.这里有什么有效的例子?

知识库

>负责加载/保存/更新/等我们的聚合
>例如:repo.load(orderId);

事件

>表示在聚合(或命令处理程序等,如果它们也可以触发事件)中发生的事情
>事件是不可改变的
>系统中的其他有界上下文可以使用事件来做出决策
>例如:new OrderCancelledEvent(orderId);

事件处理程序

>对发生的事件做出反应
>在相同或不同的有界上下文中,单个事件可以有多个事件处理程序
>可以与基础设施服务进行交互:OrderCancelled => OrderCancelledHandler => EmailService.sendEmail()
>可以触发新命令
>可以与Finders交谈
>当事件处理程序触发命令,与Finder对话并与基础结构交互时,它在本质上与Saga(或REST Enpoint行为)类似.除了它是对单个事件的反应,而不是对一系列事件的反应.

冒险故事

>维护一个跨越相同或多个有界上下文(坐标)的业务流程
>接收活动
>维护链/事件集的状态
>通常状态是持久的
>超时可以设置为检查/改变状态(可以有时间概念)
>国家可能有副作用,例如:发射命令,与Finder交谈,与基础设施服务交互(例如电子邮件)
>例如:
等待OrderShipped和OrderReceived事件=> fire CancelOrderCommand
等待OrderCancelled =>消防订单取消电子邮件

发现者

>用于检索上下文的readmodel
>通常返回数据传输对象(DTO)类型对象
>在我们的应用程序的写入方面不应找到Finder(耦合较少)
>单(读写)规范化数据库模型:Finder可以调用其他Finder(跨上下文)来满足嵌套对象
>读取特定的非规范化数据库模型:Finder将在一次数据库调用获取所有数据
>例如:finder.findOrdersOnDate(date);

基建服务

>交易基础设施:数据库访问,发送电子邮件,消息队列等

这是组件与责任的准确总结吗?
缺少什么,应该移动什么?
我可以用相关答案更新列表.

解决方法

就像你说的那样,有很多意见,你需要过滤它们,因为大多数时候人们在没有任何经验的情况下发表意见. CQRS是一个很大的话题,所以我不认为没有经验,你应该完全进入DDD和ES.服务应该包含在内并且边界清晰,如果您遵循这些原则,您将能够在您的域中实现不同的实现,因此,现在就开始使用CQRS,并在掌握CQRS后将DDD / ES添加到以下服务中.

我建议你这样开始构建你的体系结构的CQRS部分,一个命令的网关和一个查询的网关,因为这是常见的,只是因为有很多决定要做:

> Rest API
>消息合同/验证
>阅读模型

并且在没有DDD的情况下以更传统的方式开始实现您的服务,只使用存储库模式.当你开始感到自信时,也许你可以在聚合方面进入DDD,然后再转向ES.您可以随时更改初始服务.

我的建议是不要试图一次性完成,因为你会失败;我以前见过很多次.

For example: Wait for OrderShipped and OrderReceived events => fire CancelOrderCommand Wait for OrderCancelled => fire order cancelled email

Sagas不应该发布事件(传奇模式),传奇聚合事件和提交命令.像NServiceBus这样的框架允许sagas发布事件这一事实并没有帮助,所以要注意.

Single (read+write) Normalized Database Model: the Finder can call other Finders (across contexts) to satisfy nested objects

您希望在阅读模型中有哪些其他背景?

Infrastructure Services

Deals with infrastructure: db access,send emails,message queues,etc

不确定你的意思,但肯定看起来不对.消息队列或数据库服务??

猜你在找的HTML相关文章