Skip to content

Instantly share code, notes, and snippets.

@mattwynne
Forked from gmoeck/some_controller.rb
Created July 11, 2012 08:14
Show Gist options
  • Save mattwynne/3088890 to your computer and use it in GitHub Desktop.
Save mattwynne/3088890 to your computer and use it in GitHub Desktop.
class CommentsController < ApplicationController
def create
app.create_comment(params)
end
private
def app
MyRailsApp.new
end
end
# this is a facade over the domain which wires up the right adapters and the right domain objects
class MyRailsApp
def create_comment(params)
comment = Comment.new(params)
comment_processor.new_comment(comment)
end
private
def comment_processor
listener = FanoutAnnouncer.new(twitter_poster, facebook_poster, comment_persister)
CommentProcessor.new(listener)
end
def twitter_poster
TwitterPoster.new
end
def facebook_poster
FacebookPoster.new
end
def comment_persister
SQLCommentPersister.new
end
end
# example class
class CommentProcessor < Struct.new(:listener)
def new_comment(comment)
new_comment = comment.with_language(language_for(comment.body))
.with_spam(is_spam(comment.body))
listener.announce('new_comment', new_comment)
end
end
# immutable value object for carrying data about a comment
class Comment
include Virtus::ValueObject
attribute :body, String
def with_language
# ...
end
end
@mattwynne
Copy link
Author

You have to admit that the code in the CommentProcessor is simpler though? I'm not suggesting you use that instance for other objects, just that it owns the job of managing who is listening to events from the processor and fanning them out. I built something like this in Cucumber a long, long time ago.[1]

I don't test the facade, no. I'm still playing about with this idea, but I personally like it better than a bunch of use-case objects as my 'route in'. It keeps the controllers so simple there's almost nothing left.

[1] https://github.com/cucumber/cucumber/blob/master/lib/cucumber/broadcaster.rb

@gmoeck
Copy link

gmoeck commented Jul 12, 2012

Yes, I certainly agree that it makes the comment processor simpler, although I wonder if it lessens its cohesion. In order to send a message to the process I need one instance, and in order to subscribe to its updates I need another. I guess so long as you didn't need to be doing dynamic subscription/unsubscription outside of factories it wouldn't matter, which would probably be the case in all server side apps.

I think we're largely on the same page.

@mattwynne
Copy link
Author

mattwynne commented Jul 13, 2012 via email

@nicholasjhenry
Copy link

Just a small detail, but was interested if you would pass in the entire params hash into the facade or filter on the comment attributes. The example never specifies the comment attributes; i.e. params[:comment].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment