如何打破Grails Domain Class之间的硬依赖关系

时间:2011-03-04 00:29:30

标签: design-patterns grails domain-driven-design oop

我使用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. 将每个模块设置为插件(包含完整的域,控制器和视图),但这并不能解决问题,依赖域仍需要在相同的代码库上。
  3. 问题是,如何在grails中的域类之间创建“适配器”对象? “适配器”对象可能是服务类。使用该适配器,域之间的关系不一定在编译时检查

    也许像这样的解决方案:

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

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

2 个答案:

答案 0 :(得分:1)

你的问题非常具有挑战性,你必须经过重新设计,但......没有什么不可能。

1 - 删除循环依赖项

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

class Student {
} //no hasMany 

class ExamResult {
  Student student
}

class RaportSummary {
  Student student
}

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

2 - 将您的包装为插件

符合您要求的最佳方式是为用户,日历和学术创建grails插件,具有以下依赖关系:

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

3 - 构建您的应用

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

Et瞧。

答案 1 :(得分:0)

(3)。我没试过,但我很确定你可以use domain classes from plugins

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