There was a post on the Grails Mailing list today asking about the philosophy of Grails. This is my response:
I think I might have ripped this off from somewhere, but fundamentally there are 4 questions to answer for a basic application like this:
- How do you display data to a User?
- How do you implement business logic?
- How do you encapsulate complex business logic (Domain) interactions?
- How do you implement data access?
Most of the time when there is a layered approach one of 2 things happen. You’ve implemented a Transaction Script pattern where your business logic is implemented in the Service layer, or your Services are thin wrappers around a Data Access layer. Transaction Script is fine, but doesn’t handle complexity as well as a more Domain Driven, OO approach. The thin-wrapper thing is mostly just busy work and annoying to me.
In Grails:
- Controllers gather Data and hand it to GSPs for rendering
- Business Logic goes in Domain Objects
- Data Access goes in Domain Objects
- Complex Interaction are encapsulated in Services
Thin Controllers
Keep your controllers thin so they just mediate between views and Domains.
Active Record
2&3 happen in the same Domain objects because Grails implements the Active Record pattern. So, implement any extra queries in the Domain objects themselves.
Services for Encapsulation
Only introduce a Service when you have complex interactions (multiple objects being constructed or working together to answer a question) among multiple Domain objects that need to be encapsulated.
This is a Domain Driven framework. The complexity should be encapsulated in your Domain Objects so you can use Polymorphism to manage complexity.
Hiya… I disagree with your views on services. Services are great for all non-view preparation functionality. You should make controllers very thin like you say, but pushing too much functionality into domain classes is bad news, because even with logic related to a single domain class you may need to expose this functionality later as a SOAP, REST, XMLRPC or other service technology.
Our domain classes are not anaemic – we put functionality related to the class in there in our apps, but typically this is very minimal on the basis that anything that is not just for preparing/managing the domain model is functionality and that may be exposed via many different outlets.
Marc,
Thanks for the comment. I don’t mean to disparage using Services at all. It is of course a great way to share functionality. But whether logic is implemented in a Domain class or a Service, it can still be shared and exposed through multiple means.A Controller will most likely be used to expose those Services. Rendering an HTML page, XML for a REST service or other content is a content negotiation issue best managed by Controllers. That controller can interact with Domain objects or Services, whichever makes the most sense.
I’m fighting the idea that everything needs to be encapsulated in a Service. In this mindset, Services often become simple pass-through objects that just add extra layers and more work without adding much value. Use Services when they make sense, but have a reason.
Either way, thanks for the different perspective.
services, adding a layer that does nothing, just expose funcionality already implemented. I’m with Geoff, logic to the model. Do you wanna foo service? Use the controller for making simple calls to the model layer, the same model could be use for rendering anything.
(I guess Marc cames from java world, and he hasn’t try frameworks like grails or similar stuff that makes things so much easier).