首页 > 解决方案 > Java 8 应用层和具体的输出转换

问题描述

我有一个 gradle 多项目,其中有 2 个子项目试图模拟六边形架构:

  1. 休息适配器
  2. 应用层

我不希望应用程序服务公开域模型,也不希望强制将特定表示作为输出。所以我想要应用程序服务消耗 2 个参数(一个命令和something)并返回一个T. 客户端配置服务。

其余适配器无法访问域模型,因此我无法返回域模型并让适配器创建其表示。

怎么样something。我试过 :

  1. 有签名<T> List<T> myUseCase(Command c, Function<MyDomainModel, T> fn)。应用层是转换函数的所有者(因为签名使用 MyDomainModel)并公开函数字典。所以其余控制器引用了 Fn 之一。有用。我正在寻找更好的方法。如果它存在,则更优雅的方式。
  2. 有一个签名<T> List<T> myUseCase(Command c, FnEnum fn)对于每个枚举我都关联了一个函数。有了这个,我发现签名更优雅:消费者从枚举中提供了它想要的转换。但不起作用,因为通用方法无法编译。无法解决。目前,我没有找到方法。
  3. 与 java 8 消费者或供应商或其他东西有关的东西,但我没能解决问题。

我觉得对于这类问题有一个更优雅的解决方案:接受一个函数的服务,该函数可以转换和构建客户端提供的输出。

标签: java-8domain-driven-designhexagonal-architecture

解决方案


我觉得对于这类问题有一个更优雅的解决方案:接受一个函数的服务,该函数可以转换和构建客户端提供的输出。

您正在跨应用程序和 REST 层之间的边界发送数据(可能是在应用程序和 REST 使用者之间);考虑消息传递模式可能很有用。

例如,应用程序可以定义服务提供者接口,该接口定义了用于从应用程序接受数据的合同/协议。

interface ResponseBuilder {...}

void myUseCase(Command c, ResponseBuilder builder)

REST 适配器提供了一个实现,ResponseBuilder它可以接受输入并从中生成一些有用的数据结构。

响应构建器语义(接口中函数的名称)可能来自域模型,但参数通常是原语或其他消息类型。

CQS 意味着查询应该返回一个值;所以在那种情况下,你可能更喜欢类似的东西

interface ResponseBuilder<T> {
    ...
    T build();
}

<T> T myUseCase(Command c, ResponseBuilder<T> builder)

如果你仔细看,你会发现这里没有魔法;我们只是从应用程序和适配器之间的直接耦合切换到与合同的间接耦合。

编辑

我的第一个解决方案是使用Function<MyDomainModel, T>与您的 ResponseBuilder 有点不同的 a ;但同样如此。

它几乎是双重的。使用限制较少的签名可能会更好一些myUseCase

<T> 
List<T> myUseCase(Command c, Function<? super MyDomainModel, T> fn)

依赖结构本质上是相同的——唯一真正的区别是 REST 适配器耦合到什么。如果您认为域模型是稳定的,并且输出表示会发生很大变化,那么函数方法将为您提供稳定的 API。

但是,我怀疑您会发现输出表示在域模型之前很久就稳定了,在这种情况下,该ResponseBuilder方法将是更稳定的选择。


推荐阅读