问题标签 [dddd]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
domain-driven-design - 如何在不同的有界上下文中创建两个聚合?
关于整合有界上下文的问题。
例如。我organization AR
在indentity BC
. 而courier service AR
在logistics BC
. 它们必须连接。
organization AR
由组成:
- 组织 ID
- 姓名
- 税法
- 合法地址
- ...
courier service AR
由组成:
- CourierServiceId
- 姓名
- 交通优先
- 评分
- ...
客户在一个请求中发送所有这些信息(姓名、税码、法律地址、TransportationPriority、Rating)。
问题:
- 我应该在哪个应用程序中提交创建两个 AR 的请求?
- 我应该如何创建两个 AR?在第一个 BC 中创建第一个 AR 后,我应该如何从第二个 BC 创建第二个 AR?
我面临的问题:
起初我想在organization AR
创建通知logistics BC
和创建时发布域事件courier service AR
。但是当我在第一个 BC 中发布域事件时,我必须使用语言概念作为TransportationPriority, Rating
(在第二个 BC 中创建 AR 所需的)。但这种语言概念并不属于公元前。但是它们被用于其中。据我所知,这是错误的。
那么我该如何解决我的问题呢?对不起,我的英语不好。非常感谢。
c# - 在具有多个数据库的领域驱动设计 DDD 上添加项目的最佳方法是什么?
解决方案:
- API - 包含控制器并公开 API
- 应用程序- 包含仅适用于 API 的特定业务规则
- Common - 包含常量
- 域- 它包含使用 DDD 洋葱架构的实体
- 基础设施- 处理外部 API 事务
- 持久性- 域到数据库的配置和映射
我的解决方案中有一组项目(见上文),但是,整个解决方案只处理一个数据库。现在,我计划集成另一个数据库,在具有多个数据库的领域驱动设计 DDD 上添加项目的最佳方法是什么?
最初,我正在考虑添加另一个持久性项目,但我认为它需要域。我不确定将映射到不同数据库的域混合是否正确。有人可以告诉我如何解决这个问题吗?
architecture - 与 DDD + CRQS + ES 的并发
我研究 DDD 已经有一段时间了,偶然发现了 CQRS 和事件溯源 (ES) 等设计模式。这些模式可用于帮助以更少的努力实现 DDD 的某些概念。
然后我开始开发一个简单的软件来实现所有这些概念。并开始想象可能的失败路径。
只是为了澄清我的架构,下图描述了一个来自前端并到达控制器的请求,我是后端(为简单起见,我忽略了所有过滤器、活页夹)。
- 演员发送一份表格,其中包含他想从一个帐户中提取的金额。
- 控制器将视图模型传递给应用程序层,在那里它将被转换为一个命令
- 应用层打开一个工作单元 (UOW) 将 VM 映射到命令并将命令发送到调度程序。
- 调度程序找到知道如何处理命令(帐户)的相应聚合类,并向工厂请求帐户的特定实例。
- 工厂创建一个新的帐户实例并从事件存储中请求所有事件。
- 事件存储返回帐户的所有事件。
- 工厂将所有事件发送到聚合,以便其内部状态正确。并返回帐户的实例。
- 调度程序将命令发送到帐户,以便对其进行处理。
- 帐户检查它是否有足够的钱进行提款。如果有,它会发送一个新事件“MoneyWithdrawnEvent”。
- 此事件由更改其内部状态的聚合(帐户)处理。
- 应用程序层关闭 UOW,当它关闭时,UOW 检查所有加载的聚合以检查它们是否有新事件要保存到事件存储中。如果有,它将事件发送到存储库。
- 存储库将事件持久化到事件存储区。
可以添加许多层,例如:聚合的缓存、事件的缓存、快照等。
有时 ES 可以与关系数据库并行使用。因此,当 UOW 保存已发生的新事件时,它还将聚合保存到关系数据库中。
ES 的好处之一是它有一个中心数据源,即事件存储。因此,即使内存甚至关系数据库中的模型损坏,我们也可以从事件中重建模型。
有了这个事实来源,我们可以构建其他系统,以不同的方式使用事件来形成不同的模型。
但是,要使其发挥作用,我们需要真理的来源是干净的,没有被破坏的。否则所有这些好处都不会存在。
也就是说,如果我们考虑图像中描述的架构中的并发性,可能会出现一些问题:
- 如果actor在一个排序周期内向后端发送了两次表单,并且后端启动了两个线程(每个请求一个),那么他们将调用两次应用层,并启动两个UOW,以此类推。这可能导致将两个事件存储在事件存储中。
这个问题可以在很多不同的地方处理:
前端可以控制哪些用户/参与者可以执行什么操作以及执行多少次。
Dispatcher 可以拥有所有正在处理的命令的缓存,并且如果存在引用同一聚合(帐户)的命令,它会引发异常。
存储库可以在保存之前创建聚合的新实例并运行事件存储中的所有事件,以检查版本是否仍与步骤 7 中获取的版本相同。
每个解决方案的问题:
前端
- 用户可以通过编辑一些 javascript 来绕过这个限制。
- 如果打开了多个会话(例如不同的浏览器),则需要一些静态字段来保存对所有打开的会话的引用。并且有必要锁定一些静态变量来访问该字段。
- 如果有多个服务器用于执行特定操作(水平缩放),则此静态字段将不起作用,因为有必要在所有服务器之间共享此字段。因此,需要一些层(例如 Redis)。
命令缓存
为了使该解决方案起作用,有必要在读取和写入命令缓存时锁定命令缓存的某些静态变量。
如果有多个服务器用于正在执行的应用程序层的特定用例(水平扩展),则此静态缓存将不起作用,因为有必要在所有服务器之间共享它。因此,需要一些层(例如 Redis)。
存储库版本检查
为了使该解决方案起作用,有必要在进行检查(数据库版本等于步骤 7 中获取的版本)和保存之前锁定一些静态变量。
如果系统是分布式的(水平规模),则有必要锁定事件存储。因为,否则,两个进程都可以通过检查(数据库的版本等于步骤 7 中获取的版本),然后一个保存,然后另一个保存。并且根据技术,不可能锁定事件存储。因此,将有另一个层来序列化对事件存储的每次访问并添加锁定存储的可能性。
这种锁定静态变量的解决方案有点好,因为它们是局部变量并且非常快。但是,依赖于 Redis 之类的东西会增加一些较大的延迟。如果我们谈论锁定对数据库的访问(事件存储),甚至更多。甚至更多,如果这必须通过另一项服务来完成。
我想知道是否有任何其他可能的解决方案来处理这个问题,因为这是一个主要问题(事件存储上的腐败),如果没有办法解决它,整个概念似乎是有缺陷的。
我对架构中的任何变化持开放态度。例如,如果一种解决方案是添加一个事件总线,以便所有内容都通过它汇集,那很好,但我看不出这能解决问题。
我不熟悉的另一点是卡夫卡。我不知道 Kafka 是否为这个问题提供了一些解决方案。
dddd - |#1060 - 重复的列名 'id'
这是我的mysql语句:
我收到此错误:
|#1060 - Duplicate column name 'id'
你能帮我吗?
aggregate - 哪个是在 DDD 中分离聚合的最佳方法
我正在学习 DDD,我不清楚如何将对象分成聚合。
一个例子:
我有 3 个对象:公司、商店、工作。
我有一些关系:一家公司有很多商店,一家商店有很多工作。
我想:
没有公司,商店就无法存在。一家公司必须有商店,这是真实的世界。因此,我将公司和商店合并为一个集合。
Job 是另一个聚合体。
另一个想法
找工作时,我总是关心这份工作属于哪家商店。因此,我将:购物和工作归为一个集合。
公司是另一个集合体。
哪种方式是正确的?
谢谢
asp.net - 同时使用 Application Service 和 Manager 的目的是什么?
我不是一个有经验的程序员。我总是浏览源代码来学习一些东西。ASP.NET Boilerplate 是我最喜欢的一个。昨天,我注意到有友谊应用服务(在服务/应用层)和友谊管理器(在业务/领域层)。我不明白为什么会有友谊经理。友情服务还不够?
microservices - 微服务与服务协同
在微服务架构的上下文中,单个业务操作可能需要两个或多个服务之间的协作。
假设我们有一个订单管理服务和一个产品目录服务。当用户将订单项目添加到订单时,订单管理服务将保留一个 OrderItem 对象,该对象具有以下属性:
为了让 Order Management Service 填充 ProductName 属性,我们有 4 个选择,如我所见:
选择 1:ProductName 由客户端应用程序给出,因为它可能已经拥有来自先前请求的数据
选择 2:如果架构使用 Api 网关,网关将负责从产品目录服务中检索产品名称,然后将其提供给订单管理服务。
选择 3:订单管理服务将直接调用产品目录服务并要求他提供产品 ID 给定的产品名称。
选择 4:订单管理服务在其自己的数据库中有重复的(但不是详尽的)产品信息,每次从产品目录服务接收到更新事件时,这些数据都会更新。
在这 4 个选择中,n°1 对我来说似乎不太合适,因为我们不能相信客户会给我们一个正确和更新的 ProductName 值。
我想听听您对您认为最好的选择是什么以及原因的看法!
谢谢 !
里亚纳
architecture - 如何在可能发生冲突的分布式有界上下文中收敛状态?
我有一个特定于域的任务管理的有界上下文。一些用户(称为协调者)可以创建任务并将其分配给另一个用户(称为执行者)。Executor 可以在稍后的某个时间完成任务。与此同时,协调者可以将任务重新分配给不同的执行者,后者负责完成该任务。第一个执行者失去了处理任务的能力。
现在情况变得复杂了,因为协调员在 web 应用程序(后端)工作,而执行程序在他们的移动应用程序(客户端)工作。因此,有界上下文有效地分布在许多节点之间。此外,移动应用程序可能会在相当长的一段时间(几天)内完全离线工作。
因此,可能是协调器将任务分配给 executor A
,然后 executor 离线。在metime coordinator 决定他不想等待 executor 完成任务A
并将任务重新分配给 executor B
。但是A
由于某些原因,执行者并不知道它并完成了任务。一段时间后执行者A
上线,现在我们必须在他的移动应用程序和后端之间一致地同步状态,遵循声称任务只能由其实际执行者完成的业务规则。执行者A
告诉后端“嘿,我用那个结果完成了任务”。后端听了 executorA
然后他看到当前分配给 executor 的任务B
。后端必须回答执行者A
:“对不起,目前任务不是你的,请删除手机上的任务,我拒绝你完成任务的结果。”
真实场景要复杂得多:执行者和协调者可以完全独立地完成多种动作,任务。然后在稍后的某个时间,他们应该按照业务规则正确同步状态。
您将如何在假设冲突解决(拒绝、补偿等)的分布式有界上下文中实现此类同步?
api - 在 DDD(域驱动设计)中创建域之前的中间计算调用
我有一个接受访客订单的用户界面。访客下订单后,UI 有一个计算税金的按钮,并在下实际订单之前返回 UI。
我有 基于 DDD 的订单 API,带有 ADD、UPDATE、GET、GET ALL 和 DELETE 端点。但是对于中间的“获取税”按钮,我该怎么办?它是查询(CQRS)端操作还是与不同服务类对话以在域创建之前获取结果的 API 端点。
domain-driven-design - DDD 域实体与持久性实体
在 DDD 中,我们说域实体不是数据库模型/实体的表示。我们还说,为了正确地从应用程序中提取领域模型,领域模型不应该有任何关于它的持久化方式或返回给客户端的方式的信息。
我遇到的问题是,在处理大多数 ORM 或数据库抽象时,我们需要使用一些特定于数据库的注释来注释数据库实体,从而违反规则。
这是否意味着我们应该为域创建一个实体,为持久化创建另一个实体?
我对此很陌生,不确定正确的方法是什么。