[rspec-users] Depot app, Demeter's law and troubles cleanly specing

Matt Wynne matt at mattwynne.net
Sun Apr 19 16:37:57 EDT 2009

On 19 Apr 2009, at 19:54, David Chelimsky wrote:

> On Sun, Apr 19, 2009 at 11:24 AM, Mark Wilden <mark at mwilden.com>  
> wrote:
>> On Sun, Apr 19, 2009 at 3:51 AM, Matt Wynne <matt at 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

More information about the rspec-users mailing list