[rspec-users] How to spec code with multiple (interacting) paths
jerry.west at ntlworld.com
Mon Feb 26 05:50:03 EST 2007
> This would be acting like a factory for all objects required by the
> action, and could be specified independently. Then I wouldn't need
> to check that the controller behaves correctly under 3 different
> invalid models, just that if anything is invalid it behaves
> correctly. (Pretty much identical to the way you spec the individual
> validations in a model, then spec that the controller behaves
> correctly if its invalid.)
> Maybe you were thinking along these lines? It's hard to put things
> across sometimes without writing code out.
Yes, I think so; the controller delegates the matter where possible, so
your controller spec simply checks that the delegatee is called. The
spec for the delegate(e) worries about ensuring that the correct
outcomes arising in each of the myriad parameter combinations.
I've also been puzzling over the true application of "Tell don't ask",
which I haven't really wrapped my head around yet. To quote...
The problem is that, as the caller, you should not be making decisions
based on the state of the called object that result in you then changing
the state of the object. The logic you are implementing is probably the
called object's responsibility, not yours. For you to make decisions
outside the object violates its encapsulation.
Sure, you may say, that's obvious. I'd never write code like that.
Still, it's very easy to get lulled into examining some referenced
object and then calling different methods based on the results. But that
may not be the best way to go about doing it. Tell the object what you
want. Let it figure out how to do it. Think declaratively instead of
It is easier to stay out of this trap if you start by designing classes
based on their responsibilities, you can then progress naturally to
specifying commands that the class may execute, as opposed to queries
that inform you as to the state of the object.
I'm too used to designing my models around the data which means I always
offer the equivialent of #is_valid and #set_status. Tell don't ask
suggests I should be writing CreditCard#transact and returning an error
if necessary. It's a bit of a sea change for me (and for DHH if I
recall his early works correctly!). All part of the heavyweight model
thing that seems to be in fashion, perhaps.
More information about the rspec-users