如何打破 Grails 域类之间的硬依赖
我已经使用 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]
}
因为对级别代码的依赖,我无法分离用户,日历,学术领域类,甚至有些客户不需要学术模块。应用程序是紧密耦合的,因为域类无法分离。
我想到了一些替代方案:
- 实现动态域插件以使域类更加可移植(http://burtbeckwith.com/blog/?p=364),但我仍然困惑如何将其集成到应用程序中将
- 每个模块作为插件(具有完整的域,控制器和视图),但这并不能解决问题,依赖域仍然需要在相同的代码库上。
问题是,如何在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 :
- 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
- 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你的问题非常具有挑战性,你将不得不重新设计,但是......没有什么是真正不可能的。
1 - 删除循环依赖项
如果不删除这些依赖项,您就没有机会模块化您的应用程序。
由于 user 是您的基础包,因此您需要从此包中删除任何外部依赖项。在您的示例中,这意味着
Student
域必须删除对ExamResult
和RaportSummary
的引用,然后
您可以创建一些方法,例如
RaportService.getRaports(student) { Raports.findAllbyStudent(student)}
2 - 将你的包作为插件
满足你的要求的最好方法是为用户、日历和学术创建 grails 插件,其依赖项如下:
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 toExamResult
andRaportSummary
i.e.and
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 independantcalendar
plugin is independant (or maybe depends on user plugin)academic
plugin depends onuser
andcalendar
plugin3 - 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.
(3)。我没有尝试过,但我很确定您可以 使用插件中的域类。
因此,您可以创建以下插件:
user-core
、calendar
(取决于user-core
)和academic
(取决于user-core
和calendar
),每个都提供自己的域类并使用依赖项中的类。因此您不必通过插件重复类。(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 onuser-core
) andacademic
(depending onuser-core
andcalendar
), each providing own domain classes and using classes from dependencies. So you won't have to duplicate classes over plugins.