Rest 在域驱动设计中,调用另一个有界上下文的应用程序服务可以吗?
我正在读沃恩·弗农的《实现领域驱动设计》。在其中一个例子中,他展示了一个在协作范围内创建的论坛。在创建之前,将实例化Creator值对象。创建者对象的信息来自不同的有界上下文。向RESTAPI发出HTTP请求,以从标识和访问绑定上下文检索用户。然后将其转换为创建者对象Rest 在域驱动设计中,调用另一个有界上下文的应用程序服务可以吗?,rest,domain-driven-design,integration,Rest,Domain Driven Design,Integration,我正在读沃恩·弗农的《实现领域驱动设计》。在其中一个例子中,他展示了一个在协作范围内创建的论坛。在创建之前,将实例化Creator值对象。创建者对象的信息来自不同的有界上下文。向RESTAPI发出HTTP请求,以从标识和访问绑定上下文检索用户。然后将其转换为创建者对象 private Forum startNewForum( Tenant aTenant, String aCreatorId, String aModeratorId,
private Forum startNewForum(
Tenant aTenant,
String aCreatorId,
String aModeratorId,
String aSubject,
String aDescription,
String anExclusiveOwner) {
Creator creator =
this.collaboratorService().creatorFrom(aTenant, aCreatorId);
Moderator moderator =
this.collaboratorService().moderatorFrom(aTenant, aModeratorId);
Forum newForum =
new Forum(
aTenant,
this.forumRepository().nextIdentity(),
creator,
moderator,
aSubject,
aDescription,
anExclusiveOwner);
this.forumRepository().save(newForum);
return newForum;
}
UserInRoleAdapter在另一个有界上下文中调用RESTAPI,并将其转换为Creator对象
public class TranslatingCollaboratorService implements CollaboratorService {
private UserInRoleAdapter userInRoleAdapter;
...
@Override
public Creator creatorFrom(Tenant aTenant, String anIdentity) {
Creator creator =
this.userInRoleAdapter()
.toCollaborator(
aTenant,
anIdentity,
"Creator",
Creator.class);
return creator;
}
...
}
private T extends <Collaborator> T newCollaborator(String aUsername,
String aFirstName,
String aLastName,
String aEmailAddress,
Class<T> aCollaboratorClass)
throws Exception {
Constructor<T> ctor =
aCollaboratorClass.getConstructor(
String.class, String.class, String.class);
T collaborator =
ctor.newInstance(
aUsername,
(aFirstName + " " + aLastName).trim(),
aEmailAddress);
return collaborator;
}
从RESTAPI检索的JSON用于实例化Creator对象
public class TranslatingCollaboratorService implements CollaboratorService {
private UserInRoleAdapter userInRoleAdapter;
...
@Override
public Creator creatorFrom(Tenant aTenant, String anIdentity) {
Creator creator =
this.userInRoleAdapter()
.toCollaborator(
aTenant,
anIdentity,
"Creator",
Creator.class);
return creator;
}
...
}
private T extends <Collaborator> T newCollaborator(String aUsername,
String aFirstName,
String aLastName,
String aEmailAddress,
Class<T> aCollaboratorClass)
throws Exception {
Constructor<T> ctor =
aCollaboratorClass.getConstructor(
String.class, String.class, String.class);
T collaborator =
ctor.newInstance(
aUsername,
(aFirstName + " " + aLastName).trim(),
aEmailAddress);
return collaborator;
}
private T extends T newCollaborator(字符串aUsername,
字符串作为第一个名称,
字符串名称,
字符串地址,
A类(B类)
抛出异常{
构造器=
aCollaboratorClass.getConstructor(
String.class,String.class,String.class);
合作者=
.newInstance(
奥瑟南,
(aFirstName+“”+aLastName).trim(),
地址);
返回合作者;
}
对RESTAPI的调用是否等同于直接在另一个有界上下文中调用应用程序服务方法?或者有什么不同?是否允许在其他有界上下文中直接调用应用程序服务,然后转换结果?使用RESTAPI在有界上下文之间直接通信是否常见
编辑:我的问题类似于一个问题,但我只是想了解更多的信息。在这个问题上,据说最好使用事件并保留数据的本地副本,而不是在另一个有界上下文中调用应用程序方法。如果将这些应用程序方法放在REST接口之后,是否仍然更倾向于使用事件。是否总是不赞成直接调用其他有界上下文的应用程序方法,还是应该尽可能少地使用它 有界上下文边界与消息传播方式无关。由架构师决定如何组织应用程序,是否将其分解为微服务等。重要的是要明确和严格地描述接口。REST、RPC或直接调用,你可以说,只是一种传输 当然,几乎从定义上讲,与外部事物相比,有界上下文中的概念更紧密地耦合在一起,这通常使单独的服务成为可能,但我怀疑DDD是否坚持任何特定的方式。这本书在“映射三个上下文”中提到了开放主机服务模式,比如说:“我们通常认为开放主机服务是一个远程过程调用(RPC)API,但它可以使用消息交换来实现。”这可能正是这本书的作者的观点 我认为,有时(本书中也提到了这一点),反腐败层(协作上下文)用于有效的解耦,因为在本书示例中,创建者是协作上下文概念,用户来自另一个服务,协作只需要某些方面(这本书描述得很详细,我不想重复) 我看到的直接调用的唯一问题是,在进行直接调用时,使适配器“如果稀薄的空气”可能会让一些人感觉“过度使用”,最终用户可能会被使用。而在其他情况下,从心理上更容易将外部上下文的概念转换为所讨论的上下文中使用的内容 虽然不直接相关,但以下问题/答案可能会为您提供更多见解: 使用具体的消息传递技术与应用DDD方法是正交的。它更适合于特定情况和所需的系统特性,也可能是一个意见问题。例如,是否保存(缓存?)来自另一个有界上下文的信息由软件设计师决定。不是来自DDD书籍,而是您构建的分布式系统的解决方案取决于需求,没有通用的答案可以指导您
在同一位作者的另一本书——《领域驱动设计精粹》,第4章。具有上下文映射的战略设计中,您可以找到一些澄清,引用:"您可能想知道将提供哪种特定类型的接口来允许您与给定的有界上下文集成。这取决于拥有有界上下文的团队提供的内容。它可以是通过SOAP的RPC,或具有资源的RESTful接口,也可以是使用队列或发布订阅的消息传递接口。至少在某些情况下,您可能会被迫使用数据库或文件系统集成,但希望不会发生这种情况。。。"你能为这本书添加一个代码片段或至少更好的参考吗?@RomanSusi的可能重复项我更新了问题以解决可能的重复项。@Benten更新了答案,基本上保持不变:DDD不能轻易为你修复所需的系统特性,你需要知道域的要求,包括对时间、可伸缩性要求等进行限制。通常不可能回答。因此,如果用直接调用替换REST调用,则不会有太大问题。反腐败层和转换器将保持基本相同。是的。只需确保边界非常清晰,并定义了接口。REST也是一样的,对吗因为在实践中,没有什么可以防止两个微服务的代码库混淆。传输在域模型级别是(或者至少在理想情况下应该是)无关的。使用反腐败层的主要原因是避免用外来概念污染无处不在的语言。