2016-09-29 74 views
0

我想通过Repository的示例了解六边形体系结构。 在这个设置中,我有以下几层:框架(基础结构) - >应用程序 - >域。存储库中的六边形体系结构

我有User在域部分,可以说我想验证User如果没有任何重复通过DuplicateUsernameValidator。为了获得这些信息,我需要从某处获得这些信息。我在域层再次添加了一个接口UserRepository,这样它可以在上面的层中解决。

这是对我来说很棘手的部分。我想要实现UserRepository的逻辑,但对我来说,在应用程序层中实现这一点是没有意义的,因为持久化上下文位于基础结构层(例如JdbcUserRepositoryJpaUserRepository)。 但是,如果我正确理解六角形结构,则不能直接在我的基础结构层中实现接口UserRepository,因为基础结构层不应该知道域层。

我错过了什么?

回答

2

我认为你所面临的困惑来自于你试图从六角形体系结构的角度来看待现有的三层应用程序。
让我们来简单吧。
让我们暂时忘记它是什么“应用层”。
你有你的六边形,如果我理解正确,它包含你的应用程序的域(用户对象)。
正确地,您正在定义一个端口在您的六边形内,允许您从其他位置检索用户。 (我在说的是UserRepository接口
您的端口(JdbcUserRepositoryJpaUserRepository)的所有实现都将代表您的端口的适配器,并且应该位于您的六边形之外,以便不会将适配器的低级别细节连接到更高级别的策略
就是这样
可能难以理解的部分是了解六角形内部发生了什么,以及不是从具有三层架构(或某种...)的应用程序开始。
保持六边形内部什么是与你的域名完全相关的,而不是与基础设施相关的。
向外移动一切与外部世界相关,但不包含任何业务l逻辑。
分离并相应地移动它,一切都具有上述两种情况。

+0

有一件事我不明白是什么把像'JpaUserRepository'实现在基础设施层的点。例如,'User findByName(String userName)'方法将基本实现为'qry = em.createQuery(“从用户u中选择u,其中u.name =?1”); qry.setParameter(1,userName);返回qry.getSingleResult();'。它只使用领域语言和抽象基础结构API(JPA API和JP-QL DSL)。将其置于域层中会出现什么问题,传统的分层体系结构就是这种情况?是不是六角矫枉过正? –

+0

当你考虑到许多真实世界的查询不可避免地在其中嵌入业务逻辑时,它变得更加难以理解。例如:'从e选择e从SomeEntity e其中e.status =:请求和不存在(...)'。其中一些查询非常长,并嵌入了大量单独的业务规则。将它们写在域图层外面看起来不太合适... –

+0

我不认为它是过度的。有很多原因可以避免将基础设施细节放入核心域。主要的是:耦合。 将数据库代码放在自己的适配器中的优点是什么? 很多: - 责任分离:如果我必须改变如何从我的数据库中检索数据,我不必修改相对于我的业务逻辑的类/模块; - 个人“可发展性”:例如一个开发人员可以改善查询性能,另一个开发人员可以解决业务逻辑问题,而不会出现大问题 –

1

我想知道完全相同的问题,这里是我的结论:您正在讨论的实现是由适配器处理的。

您已将业务层开发为六角形。好!这意味着,您的实现取决于暴露于外部的合同(= API接口)。在同样的想法中,您的实现使用其他接口来与外部进行通信(=您称为UserRepository的SPI接口)。由于这些界面,您的六角形与外界隔离。 当你的六角形被实例化时,你的SPI的实际实现应该作为参数传递(控制反转)。

现在,在您的底层,您将通过实现适配器(适配器模式)来实现Jpa逻辑。

您的适配器(例如可以是Spring服务)将实现您的接口UserRepository并包装您的JpaUserRepository。然后,您的UserRepository中的每个方法都将被重定向到JpaUserRepository的相应方法(有或没有一点适应)。

enter image description here