【问题标题】:How to break hard dependency between Grails Domain Class如何打破 Grails 域类之间的硬依赖
【发布时间】:2011-03-04 00:29:30
【问题描述】:

我已经使用 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"] 

}

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

【问题讨论】:

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


    【解决方案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 - 构建您的应用

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

    等等。

    【讨论】:

    • 感谢您的评论,我认为这是目前最可行的方法。
    【解决方案2】:

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

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

    【讨论】:

    • 我仍然对这种方法有疑问。的确,您可以使用插件中的域类,但它仍然会在域类之间产生硬依赖。它仍然让我下载所有可靠的域,并且可能是一个完整的应用程序。我想要的是“打破”由域类关联引起的硬依赖。我更喜欢动态域方法,它允许我在运行时创建域类,但仍然没有如何管理域的方法。
    • 当您提到代码耦合时,我认为您希望在 开发 时分离代码。单独的插件将允许您只使用您需要的那些类。现在我可以看到问题是什么了。
    • 我想澄清一下,为什么在我的情况下最终会下载所有应用程序。因为当核心域(例如学生)中发生 hasMany 时,即使在某些情况下我不打算包含学术模块,也会使该核心域依赖于某些模块(例如学术)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多