如何打破 Grails 域类之间的硬依赖

发布于 2024-10-20 02:54:41 字数 1332 浏览 1 评论 0原文

我已经使用 grails 构建了一个应用程序,从逻辑上讲,系统分为一些模块。起初,我通过实现代表模块的包来分离逻辑。

但当我需要“解耦”应用程序时,问题就出现了。因为有些客户端不需要所有模块,他们只需要一些模块,并且每个客户端的组合都不同。

技术问题是在 grails 模块之间分离代码。域类确实是紧密耦合的。我想重写我的应用程序,只是为了使分离不仅在逻辑上,而且每个模块都有单独的代码库。因此,不同的团队开发不同的模块,在不同的代码库上工作。

真正问题的例子是这样的:

模块:用户(核心),日历,学术

package user.group

import academic.RaportSummary
import academic.examResult

class Student {
  static hasMany = [exams:ExamResult,raports:RaportSummary]  
}

package calendar

class Semester {

}

package academic 

import calendar.Semester
import user.group.Student

class SubjectSummary {
  static belongsTo = [student:Student, semester:Semester]

}

class RaportSummary {
  static belongsTo = [student:Student]
}

因为对级别代码的依赖,我无法分离用户,日历,学术领域类,甚至有些客户不需要学术模块。应用程序是紧密耦合的,因为域类无法分离。

我想到了一些替代方案:

  1. 实现动态域插件以使域类更加可移植(http://burtbeckwith.com/blog/?p=364),但我仍然困惑如何将其集成到应用程序中将
  2. 每个模块作为插件(具有完整的域,控制器和视图),但这并不能解决问题,依赖域仍然需要在相同的代码库上。

问题是,如何在grails中的域类之间创建“适配器”对象? “适配器”对象可能是一个服务类。使用该适配器,域之间的关系不一定在编译时检查

可能是这样的解决方案:

class Student {

  //dependency to other modules
  //checked at runtime
  def hasManyOnOtherModules = ["exams:academic.ExamResult"] 

}

理想的实现是每个模块都可以单独运行和测试。

i've build an application using grails, logically the system is separating into some of modules. at first i was separate the logic by implementing a package that represent modules.

But the problem is occurred when i need to "decoupled" the application. Because some client doesn't need all modules, they just need some modules, and the combination is vary on every client.

The technical problem is to separating code between grails modules. The domain class is really tightly coupled. I want to rewrite my application just to make the separating is not only logically, but every modules have separate code base. So a different team that develop a different modules, working on different code base.

The example of the real problem is like this :

Modules : user (core), calendar, academic

package user.group

import academic.RaportSummary
import academic.examResult

class Student {
  static hasMany = [exams:ExamResult,raports:RaportSummary]  
}

package calendar

class Semester {

}

package academic 

import calendar.Semester
import user.group.Student

class SubjectSummary {
  static belongsTo = [student:Student, semester:Semester]

}

class RaportSummary {
  static belongsTo = [student:Student]
}

Because that dependency on the level code, i can't separate the user, calendar, academic domain class, even some client doesn't need the academic module. The application is tightly coupled, because the domain class can't be separated.

There some alternative that come in my mind :

  1. Implement dynamic domain plugin to make domain class is more portable (http://burtbeckwith.com/blog/?p=364), but i still confuse how to integrate this in application
  2. Make each modules as plugin (with complete domains, controllers, and views), but this doesn't solve the problem, the dependence domain still needed on the same code base.

The question is, how to create an "adapter" object between domain class in grails? the "adapter" object maybe a service class. With that adapter, relation between domain not necessarily check at compile time

maybe the solution like this :

class Student {

  //dependency to other modules
  //checked at runtime
  def hasManyOnOtherModules = ["exams:academic.ExamResult"] 

}

The ideal implementation is every module can be running and tested separately.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冬天的雪花 2024-10-27 02:54:42

你的问题非常具有挑战性,你将不得不重新设计,但是......没有什么是真正不可能的。

1 - 删除循环依赖项

如果不删除这些依赖项,您就没有机会模块化您的应用程序。
由于 user 是您的基础包,因此您需要从此包中删除任何外部依赖项。在您的示例中,这意味着 Student 域必须删除对 ExamResultRaportSummary 的引用

class Student {
} //no hasMany 

,然后

class ExamResult {
  Student student
}

class RaportSummary {
  Student student
}

您可以创建一些方法,例如 RaportService.getRaports(student) { Raports.findAllbyStudent(student)}

2 - 将你的包作为插件

满足你的要求的最好方法是为用户、日历和学术创建 grails 插件,其依赖项如下:

  • < code>user 插件是独立的
  • calendar 插件是独立的(或者可能取决于用户插件)
  • academic 插件取决于 user 和 < code>calendar 插件

3 - 构建您的应用程序

最后,根据您的客户,您可以单独使用学生插件或使用所有插件构建您的应用程序,

瞧。

Your question is quite challenging and you will have to go through redesign but...nothing really impossible.

1 - Remove Cycled Dependencies

Without removing these dependencies you have no chances to modularize your application.
Since user is your base package, you need to remove any external dependencies from this package. In your example, it means that Student domain will have to remove reference to ExamResult and RaportSummary i.e.

class Student {
} //no hasMany 

and

class ExamResult {
  Student student
}

class RaportSummary {
  Student student
}

Then you can create some methods like RaportService.getRaports(student) { Raports.findAllbyStudent(student)}

2 - Make your packages as plugins

The best way to match your requirements will be to create grails plugins for user, calendar and academic with dependencies like:

  • user plugin is independant
  • calendar plugin is independant (or maybe depends on user plugin)
  • academic plugin depends on user and calendar plugin

3 - Build your app

Then finally, according to your client, you can build your app with student plugin alone or with all your plugins

Et voila.

绝影如岚 2024-10-27 02:54:42

(3)。我没有尝试过,但我很确定您可以 使用插件中的域类

因此,您可以创建以下插件:user-corecalendar(取决于user-core)和academic(取决于 user-corecalendar),每个都提供自己的域类并使用依赖项中的类。因此您不必通过插件重复类。

(3). I didn't try it, but I'm pretty sure that you can use domain classes from plugins.

So you can create following plugins: user-core, calendar (depending on user-core) and academic (depending on user-core and calendar), each providing own domain classes and using classes from dependencies. So you won't have to duplicate classes over plugins.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文