0

如何在 Grails 中拆分域逻辑和数据访问(这是一个好主意)?

我们编写的许多软件应用程序都以数据(基础)为中心,在 Grails 中,通常会从服务类或控制器直接持久化到 DataSource.groovy 中配置的数据库。更改数据库很容易,但我们并不是真正独立于代码中的持久性实现。

我正在尝试编写一个为不同的持久性和数据源(不仅是数据库)实现打开的应用程序,并专注于业务领域而不是数据库实体。这也是测试时的一个优点(易于编写假/模拟持久性) 最初我只有一个持久性实现 - Grails 域类,使用 GORM。但有可能我将来希望拥有数据库以外的其他数据源,例如休息服务或其他东西。

目前,我只将数据库作为数据源,并且主要做一些杂乱无章的事情(以及一些域逻辑)。我认为我仍然停留在“旧”思维中,专注于数据库持久性,因为我的大多数业务域类都有一个 Grails 域类等价物,它是它的副本。当要持久化域类时,我只需将属性复制到 Grails 域类。

我对这个解决方案不太满意。我可以想到至少两个可能的改进/更改:

  1. 我的 Grails 域类的组织方式可能与业务域类不同,因此我不只是将属性从一个类复制到另一个类。但是,在从数据库读取或写入数据库时​​,这仍然会涉及从一个类到另一个类的大量属性映射。
  2. 也许有一种方法可以从常规的 src/main/groovy 包中使用业务领域类并用 GORM 东西装饰?或者以其他方式拆分域逻辑和持久性?我已经看到可以通过在域类上使用 hibernate conf 来做到这一点。这是唯一的方法吗?

我看过一些关于 Grails 架构的有趣讨论,包括干净的架构、六边形架构和 ddd,但我还没有找到任何示例。有吗?

在这一点上,正如我所说,大部分功能都是 CRUD 的东西,但不是全部。更进一步,应用程序可能有更多的业务逻辑,所以我不希望使用带有视图、控制器、服务、域的 Grails 的“默认”架构。我想要一个独立于 grails 视图/控制器和域/GORM 的“核心”应用程序

4

1 回答 1

0

自从您发布问题以来已经有一段时间了,但这对我来说是一个非常有趣的话题......

我目前在大型 Java8 项目中工作,这些项​​目实现了干净架构、ddd、cqrs 和六边形架构等原则。我对 Grails 1.x 项目的经验也很有限,我记得问过和你现在一样的问题。

现在我有了更广阔的视野,老实说,我认为强迫 Grails 成为一个干净的架构是没有意义的。你将经历一段非常痛苦的尝试来实现它,而且你可能不会对结果感到满意。

Grails 中的所有内容都旨在以一种固执己见的、基于约定的方式使用。从 GORM 作为一个 ActiveRecord 实现开始,然后按照他们对目录结构、您需要定义的工件的语义(控制器、服务、模型......)等所做的每一个小决定。我不是说这个不好。事实上,当您开发适合这种事物模式的东西时,这非常棒。

您的工件之间的这种耦合和隐式行为使得除了您的数据访问(或您的 http 交互,或与第三方的任何其他交互)之外,很难对您的业务逻辑进行建模。

从 DDD 的角度来看,您应该更喜欢基于数据或集合的存储库而不是 ActiveRecord 实现。然后,您可以开始将持久性逻辑与域模型分离。在与持久层保持类似 ActiveRecord 的交互的同时尝试这样做会产生一个非常“肮脏”的适应层,并带有大量重复。

例如,在尝试使用应该放入不同数据库表的聚合对象来调整复杂域时,您将遇到非常困难的情况。

现在,解决您建议的两个改进,这就是我可以告诉您的:

  1. 我的 Grails 域类的组织方式可能与业务域类不同,因此我不只是将属性从一个类复制到另一个类。但是,在从数据库读取或写入数据库时​​,这仍然会涉及从一个类到另一个类的大量属性映射。

你确实可以按你说的去做。只需在 src/groovy 文件夹中放置一些代码。您将在这里面临的主要问题是依赖注入。当在标准目录中定义服务和控制器时,Grails 会自动注入对您的服务和控制器的依赖项。对于其他一切,您需要明确告诉 Grails 如何获取依赖项并将它们传递给您的自定义工件

  1. 也许有一种方法可以从常规的 src/main/groovy 包中使用业务领域类并用 GORM 东西装饰?或者以其他方式拆分域逻辑和持久性?我已经看到可以通过在域类上使用 hibernate conf 来做到这一点。这是唯一的方法吗?

如果你用 GORM 装饰你在 src/groovy 中定义的域对象(如果可能的话)你会遇到同样的问题。您在这里的任务是将您的域与持久性逻辑隔离开来。通过在其中包含任何 GORM 来实现它的目的是失败的。

我在这里的所有建议都是:

  1. 切换到其他耦合较少的库,让您设计自己的架构(即RatpackJooq)或
  2. 如果这不是一个选择,那就完全接受 Grails 的做事方式。

有一个非常全面的库列表,您可以浏览以获取灵感:Awesome Java

于 2015-06-14T11:36:02.743 回答