我对我的API的结构有问题。 我的API包括具有

问题描述 投票:0回答:1
域类。

动物域 - 域层

public class Study {
    private final Long id;
    private final Long employeeId;
    private Long educationLevelId;
    //Other attributes and methods
}
ACADMILEVEL域 - 域层
public class educationLevel {
    private final Long id;
    //Other attributes and methods
}

public class AcademicLevel {
    private final Long id;
    private List<educationLevel> educationLevels;
    //Other attributes and methods
}

在我的

Study
域中有一个
findStudiesByEmployeeIdUseCase

,需要返回一个

StudyDTO
动物域 - 应用程序层

public class StudyDTO {
    private Long id;
    private Long employeeId;
    private Long educationLevelId;
    private Long academicLevelId;
    //Other attributes
}
StudyDTO
需要
academicLevelId

,这是另一个域类的属性。为了解决这个问题,我创建了共享服务

FindAcademicLevelIdsByEducationLevelIdsService

(接口),其实现位于
academicLevel
域的应用层中。

共享域 - 应用程序层

public class AcademicAndEducationLevelIdDTO {
    private Long academicLevelId;
    private Long educationLevelId;
    //Getters
}

public interface FindAcademicLevelIdsByEducationLevelIdsService {
    List<AcademicAndEducationLevelIdDTO> execute(List<Long> educationLevelIds)
}
问题是实现使用
AcademicLevelRepository
(域层的接口),该实现不应根据六边形体系结构原理取决于应用层。所以我不确定要采用哪种方法。
eption1:

<R> List<R> findAcademicLevelIdsBy(List<Long> educationLevelIds, Class<R> clazz)

在此选项中,存储库实现将根据指定的类类型(使用EntityManager)返回结果列表。这样,

AcademicLevelRepository

将不取决于应用程序层。
eption2:

在第二个选项中,我将在包含所有内部DTO的域层中创建一个软件包。存储库WOULR返回内部DTO,然后将其映射到

AcademicAndEducationLevelIdDTO

。我不喜欢此选项,因为根据六边形体系结构原则,DTOS组件属于应用程序层。

如果还有其他选择,请告诉我。

我需要其他选择或帮助采取更好的选择的帮助。

因此,首先要检查的一件事是:

findStudiesByEmployeeIdUseCase

是“查询”,这是一个本质上仅读取操作吗?

如果是这样,您可能会更好地使用适当的参数调用您的数据存储,然后将结果映射到表示您将用于返回数据的表示,然后将结果映射到表示结果(又称您的DTO)

“汇总” - 相关对象的簇,我们将其视为数据更改的单位 - 当...我们没有更改数据时,可能没有用。 如果您不需要聚合,则不需要存储库(可以提供对象的内存集合的幻觉的对象)。 您通常希望有某种形式的立面,充当知道如何检索信息的代码部分之间的信息障碍,以及知道该如何处理的代码部分;但是,该立面并不一定是一个汇总,也可能不是您与域代码打包的东西。

说,如果您确实想使用域模型(因为这是在您的上下文中进行的适当权衡),那么通常的答案是在您的域模型中具有一个看起来像:


List<SomeDomainValue> execute(List<Long> educationLevelIds)

然后,在您的

application

代码中也有一个看起来像

的功能
repository domain-driven-design dto hexagonal-architecture
1个回答
0
投票

然后这两件事被组成

List<DTO> dtos = (
   (List<SomeDomainValue>) domainObjects
).map( ::someDomainValueToDTO )

在此设计中,应用程序代码知道域模型,但不相反。 <R> List<R> findAcademicLevelIdsBy(List<Long> educationLevelIds, Class<R> clazz)

...那真的很接近另一个好的选择;

Class<R>

可能不是您想要的;因为将引入的耦合。 但是您可以通过相同的想法


<R> List<R> findAcademicLevelIdsBy(List<Long> educationLevelIds, Factory<R> someFactory)

在哪里,您的想法是,有一些由域代码定义的thetounterface
,该接口被定义为接受某些域值作为参数并返回通用事物;然后,您将在应用程序代码中的接口
iMplement,该接口知道要返回的东西是适当的dto。

interface DomainModelToSomethingGeneric<R> { <R> R call(DomainValue domainValue); } 对于此示例,在您的应用程序代码中,您可能有一些看起来像

class DomainModelToDTO implements DomainModelToSomethingGeneric<DTO> {
  DTO call(DomainValue domainValue) {
    return someDomainValueToDTO(domainValue);
  }
}
在一般情况下,您所拥有的是“依赖性反转”的一种形式 - 域模型实现了协议,并定义了从呼叫者执行该协议所需的功能的收集,并且呼叫代码提供了实现所需功能

当然,这些间接措施具有成本和好处,因此您需要评估它们 - 特别是在增加间接层的额外层次,以便将来更难改变吗?

我们不要遵循这些模式,因为它们是一种使一切变得更好的神奇仪式。我们遵循这些模式,因为它们为我们为某些可能的未来做好了很好的准备。

良好的判断来自经验....


	

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.