1
votes

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.

2

2 Answers

1
votes

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.

0
votes

(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.