On 19 Apr 2009, at 19:54, David Chelimsky wrote:
On Sun, Apr 19, 2009 at 11:24 AM, Mark Wilden <m...@mwilden.com>
wrote:
On Sun, Apr 19, 2009 at 3:51 AM, Matt Wynne <m...@mattwynne.net>
wrote:
@order_presenter.product_titles do |product_title, url|
<%= link_to product_title, url %>
end
The presentation of an order in most apps will be constructed from
additional columns (e.g., color, size, price, extended price). These
columns may well be formatted differently depending on the
circumstance (e.g, printed or on-screen).
Now, it might be a good idea to put this construction and formatting
in a helper or presenter outside the view (though it won't be
TSTTCPW). But anywhere you put it, there will be non-Demeterian code
that needs to drill down into each order's items', products'
information (as well as non-product information, such as line-item
discount). If the underlying model changes, this code will have to
change - you can't avoid it.
The motivation behind demeter is to localize change. The cost is
method bloat and potential lack of cohesion on a model. Having a
single presenter object act as the one and only place that will change
besides the model itself is a good compromise between complete
localization of change in the model and method bloat on the model.
A very interesting approach to all this was presented by Allen Holub
in his talk boldly entitled "Everything You Know is Wrong," in which
he tears apart common misunderstandings about OO.
http://www.holub.com/publications/notes_and_slides/Everything.You.Know.is.Wrong.pdf
The idea, as I understand it (but, according to his basic premise, I'm
probably wrong) is to have data importers and exporters on domain
objects in order to minimize getters and setters. These collaborators
are going to take the hit of changes to the model objects, but *only*
they will if you follow this approach. In the example we're talking
about here, we'd end up with code like this in the controller:
def some_view
@order = find_order.export_to(OrderPresenter.new)
end
OrderPresenter would have a bunch of setters on it, which *the order,
which knows its own data structure* would call. Now you don't need a
bunch of getter methods on order.
Similarly, data importers would have a bunch of getters on them, and
you would use them to import data into an order like this:
order_form = OrderForm.new(params[:order])
order = Order.create_from(order_form)
I think (but I'm probably wrong too!) that this is what people like
Nat Pryce and Steve Freeman are describing when they talk about
keeping state and behaviour separate. It's something that functional
programming languages like Haskell force you to do, but it's decent
practice to use day-to-day even in languages that let you mix the two
together, IMO.
Obviously, ActiveRecord provides the getters and setters anyway, but
the real violator of encapsulation is the consumer, not the vendor.
Just because a flasher opens his coat doesn't mean that reaching
inside is a good idea ;)
LOL. I had half-written my own reply to Mark, but that says it all :)
Matt Wynne
http://blog.mattwynne.net
http://www.songkick.com
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users