

Crazy, Heretical, and Awesome: The Way I Write Rails Apps - _pius
http://jamesgolick.com/2010/3/14/crazy-heretical-and-awesome-the-way-i-write-rails-apps.html

======
raganwald
The challenge raised is that logging does not belong in the model object.
Well, I agree with that. I'm writing a Go game now, and I have notifications
sent to players when certain things happen, and I don't think they belong in
the model either.

So do I need service objects? Well, I don't know what the author of this fine
post calls them, but I am using the Observers baked into Rails, a pattern that
goes back to Smalltalk in the 1980s. I tell Rails that my NotificationObserver
is observing my Game and Action models, and the concern of notification is
separated from the concerns of playing games.

Is "Observer" the wrong word? Or worse, the wrong pattern?

~~~
jamesgolick
In retrospect, logging was absolutely the wrong example for this article. I
intend to follow up with a better example.

In the case of logging, an observer may or may not be appropriate depending on
the specifics of your application. In your Go app, it sounds like a
NotificationObserver makes perfect sense.

The broader point that I was trying to make in the article was that coupling
all of your business logic to your persistence objects is a bad idea. It
couples all of the concerns together, and with larger codebases, makes for
slow tests and code that's difficult to reason about and debug.

If your business logic lives outside of your persistence layer, service
objects can be a great way to coordinate several objects necessary to complete
some user action. Observers can work quite well too.

As long as business logic is decoupled from persistence, I think a big step
has been made towards better code.

~~~
qaexl
To me, the Service example you gave was actually another form of a controller,
albiet one that is not a classic, HTTP-oriented, stateless controller. I have
not thought this through yet -- but I suspect the state machines that manage
lifecycles would be better implemented as separate set of controllers;
"services" is an OK name for this abstraction, but there is probably a better
one.

Rails 3 makes it easier to swap out controllers and routers. (It also loads
everything under app/ by default, so you can name app/observers or
app/services without having to add in extra load paths by hand). It should not
be difficult to implement a parallel workflow engine, for example, that uses a
shared persistence stack (models) yet manages data lifecycle, and respond to
messages rather than stateless RESTful resource APIs.

Good thoughts, good article.

------
regularfry
It's slightly worrying that applying a fairly standard set of patterns should
be "crazy" or "heretical." This is one of the things I worry about in Rails -
people seem content to shove _everything_ in an ActiveRecord subclass and hope
for the best.

Still, at least doing the right thing is not only possible, but generally easy
once you've broken your mind out of the prescriptions of the framework.

~~~
jamesgolick
I'm totally with you. The title was tongue in cheek.

------
mickeyben
I don't really get what's awesome, crazy or herethical ...

