首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在清洁架构中实现REST

在清洁架构中实现REST
EN

Software Engineering用户
提问于 2018-07-01 08:12:06
回答 1查看 7.2K关注 0票数 7

我一直在使用Bob叔叔的实现一个概念应用程序的示例,并且遇到了一些问题。

Bob叔叔的体系结构要求使用接口显式地分离请求和响应。这在大多数情况下都不是问题(例如,当使用MVP模式实现UI时),但我不知道如何应用它来使用Spring创建REST。

我的Controller有一个具有以下签名的方法:

代码语言:javascript
复制
Response greet(String name)

映射到/greeting,它使用名称并根据名称的值输出不同的问候语。

注入到Controller中的是接收名称并创建问候语的UseCase,通过注入的OutputPort发送输出。

问题是,我不能以这种方式分离输入和输出,因为Controller需要与输入和输出交互才能创建响应。

我能想出的“实现”这个方法的唯一方法是使用InputPort返回值,这听起来很糟糕,根本不符合清洁体系结构的要求。

我一直在考虑这个问题,我无法找到我的Controller可以同时充当ControllerPresenter的任何方式。我是不是漏掉了什么?是否有更好的设计允许将REST的输入和输出分离,而不使事情变得过于复杂?

编辑:我又读了一遍“清洁架构”的第23章和第24章,我肯定可以更好地表达我的问题。我现在作为一个解决方案(工作,非常好)是一个一维边界(第219页),我想知道我是否可以把这个接口扩展到两个交互接口中。希望这能澄清我的观点。

EN

回答 1

Software Engineering用户

回答已采纳

发布于 2018-07-03 14:23:32

好吧,我想我明白了:你有一个上下文阻抗错配。

你现在在一个框架里,邦德先生。这里的游戏和构图有点不同。

识别的基本思想是:也就是说,“视图”随到达的每个HTTP请求而改变(更准确地说,它有一个范围耦合到HTTP连接的生存期,但这在这里并不重要)。

这意味着我们需要为每个请求创建一个新的作曲管道。

好消息是:春天已经在幕后为你做了这件事。

坏消息是,Spring使用的是单一的输入输出边界,而不是将它们分开。

我说的是“坏消息”,因为你正试图使这个圆钉与马丁所描述的方孔相吻合。我认为Spring在这里所做的是“好的”,只是不方便您想要的接口。

所以让我们假设:您有一个期望连接到输入边界和输出边界的用例交互器,并且您的控制器上有这个签名。这次又是什么?

代码语言:javascript
复制
Response greet(String name) {
    InputBoundary in = inputBoundaryFor(name);

    // Arbitrary choice
    List greetings = new ArrayList();
    OutputBoundary out = outputBoundaryFor(greetings);

    // Here's our composition with request scope.
    UseCaseInteractor uci = useCaseInteractorFor(in, out);

    uci.run();

    String greeting = greetings.get(0);

    return responseFrom(greetings.get(0));
}

如果您对UseCaseInteractor的API比较幸运,它可能会看起来像:

代码语言:javascript
复制
final UseCaseInteractor uci = ...

Response greet(String name) {
    InputBoundary in = inputBoundaryFor(name);

    // Arbitrary choice - any reasonable container for
    // for a result could be used here.
    CompleteableFuture greetings = new ArrayList();
    OutputBoundary out = outputBoundaryFor(greetings);

    uci.run(in, out);

    String greeting = greetings.get();

    return responseFrom(greetings.get(0));
}

如果我们将其构造为回调,您可能会发现这更熟悉。

代码语言:javascript
复制
Response greet(String name) {
    // Arbitrary choice - any reasonable container for
    // for a result could be used here.
    CompleteableFuture greetings = new ArrayList();

    uci.run(name, (greeting) -> {
        greetings.complete(greeting);
    });

    String greeting = greetings.get();

    return responseFrom(greetings.get(0));
}

但是,核心思想是,您有两个功能;在带有用例交互器的模块中,您有一个类似于

代码语言:javascript
复制
InputData -> OutputData

在您的web层中,您有一个类似于

代码语言:javascript
复制
OutputData -> ViewModel

输入和输出边界只是组合这两个函数的一种方式,而不引入指向错误方向的依赖关系。

票数 6
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/373413

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档