rest - 在领域驱动设计中可以调用另一个限界上下文的应用程序服务吗?

标签 rest domain-driven-design integration

我正在阅读 Vaughn Vernon 的《实现领域驱动设计》。在其中一个示例中,他展示了在协作限界上下文中创建的论坛。在它被创建之前,一个 Creator 值对象被实例化。 Creator 对象的信息来自不同的限界上下文。向 REST API 发出 HTTP 请求以从身份和访问限界上下文中检索用户。然后将其转换为 Creator 对象。

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 在另一个限界上下文中调用 REST API,并将其转换为 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;
}
...

}

从 REST API 检索到的 JSON 用于实例化 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;
}

调用REST API是否等同于直接调用另一个限界上下文中的应用服务方法?或者它有什么不同?是否允许在其他限界上下文中直接调用应用程序服务然后转换结果?拥有用于在限界上下文之间直接通信的 REST API 是否很常见?

编辑:我的问题类似于 this一个,但我只想了解更多信息。在那个问题中,据说最好使用事件并保留数据的本地副本,而不是在另一个有界上下文中调用应用程序方法。如果将这些应用程序方法放在 REST 接口(interface)后面,使用事件是否仍然更可取。直接调用其他限界上下文的应用程序方法总是不受欢迎,还是应该尽可能少地使用它?

最佳答案

有界上下文边界与消息传播方式无关。由架构师决定如何组织应用程序,是否将其分解为微服务等。接口(interface)的明确和严格很重要。 REST 或 RPC 或直接调用,随便你怎么说,都只是一种传输。

当然,几乎根据定义,限界上下文中的概念比外部事物更紧密地耦合,这通常使得创建单独的服务成为可能,但我怀疑 DDD 是否坚持任何特定方式。有问题的书在“映射三个上下文”中提到了 Open Host Service 模式等:“我们通常将 Open Host Service 视为远程过程调用 (RPC) API,但它可以使用消息交换来实现。”,这可能只是本书作者的意见。

我认为,有时(并且在书中也提到),(协作上下文的)反腐败层用于有效的解耦,因为在书中的示例中,Creator 是协作上下文的概念,而 User 来自另一个服务, Collaboration只需要一些方面(书上详细介绍了,不想重复)。

我看到的直接调用的唯一问题是,当进行直接调用时,使适配器“如果空气稀薄”可能会让某些人感觉“过大”,并且 User 可能最终会被使用。使用 REST,从心理上更容易将外部上下文的概念转化为相关上下文中使用的内容。

虽然不直接相关,但以下问题/答案可能会为您提供更多见解:Rest API and DDD .

使用具体的消息传递技术与应用 DDD 方法是正交的。它更多地取决于具体情况和所需的系统特性,也可能是见仁见智的问题。例如,是否保存(缓存?)来自另一个限界上下文的信息取决于软件设计者。不是来自 DDD 书籍,而是来自 CAP theorem 的解决方案对于您构建的分布式系统取决于需求,没有通用的答案可以指导您。

在同一作者的另一本书 - “Domain-Driven Design Distilled”,第 4 章。Strategic Design with Context Mapping 中,您可以找到一些说明,引用:“您可能想知道将提供什么样的特定接口(interface)允许您与给定的限界上下文集成。这取决于拥有限界上下文的团队提供的内容。它可以是通过 SOAP 的 RPC,或具有资源的 RESTful 接口(interface),或者它可以是使用队列或发布-订阅的消息传递接口(interface)。在最不利的情况下,您可能被迫使用数据库或文件系统集成,但我们希望这不会发生……”

关于rest - 在领域驱动设计中可以调用另一个限界上下文的应用程序服务吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41418795/

相关文章:

javascript - 使用 REST API 时,Meteor 是否保留 react 性

php - Api 平台 : Eager Loading a Subresource

angular - 使用YouTube API和Angle搜索电影预告片

c# - 读取 HttpwebResponse json 响应,C#

domain-driven-design - 在 DDD 应用程序中持久保存应用程序特定数据

domain-driven-design - 在 ddd 中,所有调用都应该通过聚合根路由吗?

client-server - 在客户端和服务器之间共享模型

java - Spring集成疑问: CRUD operations and sharing events between components

c++ - C++ 中的双数值积分

objective-c - 在混合语言项目中设置委托(delegate)