You also want to touch on higher level architectural issues like
breaking things into Plugins, etc. I recommend checking out Peter
Ledbrook's stuff on plugin-oriented architecture -
http://blog.springsource.com/2010/06/01/whats-a-plugin-oriented-architecture/
I think that you will find this distinction between services and
domain objects fairly blurred. In the past, the recommended approach
was to put much of the domain code in Services. But now, with features
like named queries in domain objects, it does make sense to have more
robust domain models.
After a while, the following formula seems to work fairly well for us:
Domain Objects - helper methods related to domain objects and the
children / parents they manage.
Controllers - only use for handling service requests and offloading
the mapping between request parameters and services.
Services - everything else.
We often find that by keeping much of the gorm code that manages
relationships in domain objects, we run either run into fewer cases of
staleObjects or these are more easily tested in isolation. You have a
little more control over catching the merge / lock errors when all
your domain interactions happen inside your domain objects rather than
in services. By moving this up into the service layer, you seem to
leak the database = domain object abstraction.
I.e, we would have methods like Offer.defineBestAllocation() within a
domain object, which will handle cases where new allocations are added
/ removed from an offer. Most of your gorm interactions are kept in
this layer.
Would like to hear more opinions on this.
> --
> You received this message because you are subscribed to the Google Groups "Grails Startup Support Group" group.
> To post to this group, send email to grails-startup...@googlegroups.com.
> To unsubscribe from this group, send email to grails-startup-suppo...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/grails-startup-support-group?hl=en.
>
>
Conceptually, breaking your application into plugins is probably a
little bit closer to modularizing it into packages.
We found that having many war files gives us a little bit more
flexibility in designing our application. Most projects I worked on
before had a CMS functionality baked right into the main application.
The plugin approach allows us to break it down into different war
packages that might have different deployment cycles while still
reusing the same functionality.
For example, a CRM, CMS and Store module that gets deployed at
different times or on different machines.
It also means that you can protect your entire application from going
down if one of your components goes rouge. We had bad experiences
where a job running awry brings down the entire app. So having a
little bit of isolation does help in this case at the expense of a
more complex deployment procedure.
Re: Code in domains vs. code in services
I think it depends on the complexity of your application. Most sites I
have built are rather dumb when it comes to getting data in and out.
So there have never been many instances where I have seen a difference
in development in services and in domain classes. Smaller, cleaner
methods in domains helps us get away from 'Sprawling Service
Syndrome', which makes it easier to debug and develop.
As the bits of code are fairly atomic in the domain objects, we often
find that it is the same effort to have integration tests that test
out the cross domain functionality ( using test-build-data ) than in
services. I also make extensive use of the grails console, pasting
code out from the domain classes that I think is defective and putting
it back into the domain class once it works. This works better than
reloading or waiting for grails to run integration tests.
I think after working with Grails for a bit, you just get into a
rhythm and understand where to put things when you are trying it out
and developing it, and where to put them when you are done. I also
find that it helped me a lot when I shifted away from the traditional
Java-esque build everything and run it in the app development approach
to using unit / integration tests.
tl;dr - integration test unit test test blargh test domain good.
--
Anything that actually changes values would follow set / get naming
convention. Just keeps it a bit saner.
We tend to use hibernate interceptors for things that have side
effects. So defineBestAllocation can be used externally but also in
the beforeUpdate closure, for example.
I think the line between what is in a service and domain object is a
little blurred. To be clear, we still use a lot of services and keep
more complex interactions in services, but push a lot of our helper
methods into the actual domain classes.
Maybe:
Internal domain class w/ child domain class ----> domain class
Internal domain class association issue ---> domain class
external system w/ external system ---> service
external system w/ internal domain class ---> service
Internal domain class w/ plugin interaction ---> service
On 19 Mar 2011, at 19:18, Tomas Lin wrote:
> Hiya,
>
> You also want to touch on higher level architectural issues like
> breaking things into Plugins, etc. I recommend checking out Peter
> Ledbrook's stuff on plugin-oriented architecture -
> http://blog.springsource.com/2010/06/01/whats-a-plugin-oriented-architecture/
>
> I think that you will find this distinction between services and
> domain objects fairly blurred. In the past, the recommended approach
> was to put much of the domain code in Services. But now, with features
> like named queries in domain objects, it does make sense to have more
> robust domain models.
>
> After a while, the following formula seems to work fairly well for us:
>
> Domain Objects - helper methods related to domain objects and the
> children / parents they manage.
>
> Controllers - only use for handling service requests and offloading
> the mapping between request parameters and services.
>
> Services - everything else.
>
> We often find that by keeping much of the gorm code that manages
> relationships in domain objects, we run either run into fewer cases of
> staleObjects or these are more easily tested in isolation. You have a
> little more control over catching the merge / lock errors when all
> your domain interactions happen inside your domain objects rather than
> in services. By moving this up into the service layer, you seem to
> leak the database = domain object abstraction.
>
> I.e, we would have methods like Offer.defineBestAllocation() within a
> domain object, which will handle cases where new allocations are added
> / removed from an offer. Most of your gorm interactions are kept in
> this layer.
>
> Would like to hear more opinions on this.
>
Hi Tomas et al,
Yeah I'm very much in the "don't do stuff in the domain classes" camp. I am often alone in this.
It does however depend on the complexity of your model and kind of application.
Whenever I have to inject a service or bean into a domain class I die a little inside. This happens so often later down the line when you realise you do need logic elsewhere that doesn't belong in the domain, it has turned me completely against "smart" domains.
For example in Weceem CMS, there's so much stuff going on behind the scenes relating to caching of metadata relating to nodes, side effects of operations on nodes etc that just cannot be done cleanly using smarts on the domain model.
E.g. before we can save a new content node domain instance, we have a whole bunch of permission checks, events and other stuff to do. Its not even viable for somebody to use the model to create a new instance and save it - it may not even be OK for them to do so.
I don't like the idea of putting stuff in the domain just to avoid other issues with the ORM. If it does help, it feels like something we shouldn't be forced in to :)
Marc
~ ~ ~
Marc Palmer
Freelancer (Grails/Groovy/Java)
Blog > http://www.anyware.co.uk
Resumé > http://www.anyware.co.uk/marc/
Twitter > http://twitter.com/wangjammer5
Grails Rocks > http://www.grailsrocks.com