In your context, I'd see models and controllers as both being parts of the business logic; the models defining "what" things are, the controllers defining "how" they are accessed.
Services sit on top, potentially exposing the business logic to anything outside of the business logic layer. I agree with you that a service might encapsulate more than one specific component (or model to be more precise).
Services and controllers contain logic
for tying various components together
to accomplish a task.
Yes, I also agree with your statement on avoiding dependancies, etc. the model should not depend on anything excpet other closely related models (Common Closure Principle).
In addition, if the logic is specific to a model - then that's where it should go; if the logic is more generic it should be placed at the approriate level - possibly a controller or a common internal utility.
Use a service rather than a controller
when the code may be used by multiple
modules or controllers.
I agree. In terms of grainularity I would see services being at a higher level of abstraction - you're more likely to expose a service to an external system than your "internal" controllers.
A model should contain as much logic
as possible but avoid referencing
application-specific functionality.
Usually a model contains at least
validation logic.
It should only contain logic that's appropriate to be there, otherwise I agree. Validation - you could abtract that out; the model should definately contain the rules that validation uses but not necessarily the validation itself. I've seen both styles used and I don't think there's no wrong or right answer as long as you're consistent.
For any piece of functionality
consider placing it in the model
first. If there is a compelling reason
not to, consider a service (also
consider the overhead and purpose for
maintain a new service). If a service
is not desired and the code won't be
reused in this application use a
controller.
it depends what that "functinality" is, if it's specific to a model then it probably belongs in the model; if it's common to more than one model then it either belongs in a controller or a common utility class within the business logic.
As I started writing all of this I wanted to put a stake in the ground around the definition of the terms you've used; I thought I'd include it anyway - so correct me if I'm wrong :) And as you can see, I'm not clear on what you mean by an "action" in your context.
- Model: (from Wikipedia - MVC) "The Model is used to manage information and notify observers when that information changes; it's also a domain-specific representation of the data upon which the application operates." To my mind this implies properties and the like - not methods.
- Controller: (from Wikipedia - MVC) "Receives input and initiates a response by making calls on model objects. A controller accepts input from the user and instructs the model and viewport to perform actions based on that input."
- Service: There are many different opinions on what a service is, I assume in your context a service is: an externally facing callable point (within the context of the layers of your system) that provides a specific answer to a specific question. (Services being usually based around business concepts not technical ones.)
- Action: I don't know what you explicitly mean by this.