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

标签 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]
}

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

我想到了一些替代方案:
  • 实现动态域插件以使域类更具可移植性(http://burtbeckwith.com/blog/?p=364),但我仍然混淆如何将其集成到应用程序
  • 将每个模块作为插件(具有完整的域、 Controller 和 View ),但这并不能解决问题,依赖域仍然需要在相同的代码库上。

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

    也许这样的解决方案:
    class Student {
    
      //dependency to other modules
      //checked at runtime
      def hasManyOnOtherModules = ["exams:academic.ExamResult"] 
    
    }
    

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

    最佳答案

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

    1 - 删除循环依赖

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

    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 - 构建您的应用程序

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

    等等。

    关于design-patterns - 如何打破 Grails 域类之间的硬依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5188334/

    相关文章:

    java - 使用备忘录/命令模式快速撤消/重做?

    php - Laravel的容器绑定(bind)机制有何不同?

    java - DDD 实现 - 存储库和工厂

    php - 将 Doctrine 与领域驱动设计结合使用

    c# - .NET 域模型,何时急切加载

    java - 设计模式 - Strategy and Bridge (Overlap in design)

    c# - WinForms 中的 MVP 导航

    grails - 为 grails 插件编写集成测试用例

    hibernate - Grails - 不要为某些请求路径打开 hibernate session

    grails - 通过键访问存储在映射中的配置变量