<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
<br>
<blockquote
cite="mid765a2c230702192014j7a365acfg3563a61301413815@mail.gmail.com"
type="cite">
<pre wrap="">(not to mention I don't understand the need for #with to mangle it's args as it does).</pre>
</blockquote>
Ah, now you're asking. <br>
<br>
<tt>#with</tt> needs to cope with a number of different types of
arguments. It could do this by using a case statement or just if/else
If there were only two options which could be passed in, that might
have been the best way to do it. But actually, the interface for #with
is really quite complex, taking different types of arguments that need
different treatment. However, although the arguments are different,
the things that need to be done to/with them are the same. <br>
<br>
Since, we're using an object oriented language, it's considered good
practice to implement this form of polymorphism<sup>[1]</sup> by
delegation - we leave the details of implementation to someone else!
Essentially, we're defining an API and implementing a different class (<tt>LiteralArgConstraint,</tt>
<tt>NumericArgConstraint,</tt> <tt>RegexArgConstraint</tt>, etc) for
each possibility (a.k.a. duck-typing<sup>[2]</sup>)<i> </i>. <br>
<br>
This simplifies the handling code immensely - all it does is iterate
over the arguments and ask the correct constraint handler to do the
right thing. Regretably the way it does this iteration has the
unfortunate side effect we are seeing. This would probably happen even
if David hadn't chosen to 'mangle the args' as he does. It's a
side-effect of <tt>Hash#each</tt>.<br>
<br>
Polymorphic delegation also makes the code more scalable (we only have
to implement a new constraint handler when someone comes up with a
super new idea (e.g. <tt>DuckTypeArgConstraint</tt>); and easier to
maintain (code is localised and hopefully it's easier to find and fix
bugs). There is an argument that the extra layer introduced adds
complexity, but IMHO once you understand the paradigm, its
interpretation is obvious and the tradeoffs are appropriate. Spaghetti
code is a nightmare to maintain!<br>
<br>
Rgds,<br>
Jerry<br>
<br>
[1] Polymorphic - having more than one form. So polymorphism in a
method is the ability to deal with arguments of different types.
Polymorphism in a class (well, classes) is the ability of different
classes to respond to the same method call, to do what is expected of
them each in their own distinctly different way. This is the posh term
for what every Ruby programmer instinctively knows because they see it
every time they use Enumerable#each on Hash, Array, or String for
example.<br>
<br>
[2] The term is a reference to the <u>duck test </u>— "If it walks
like a duck and quacks like a duck, it must be a duck". <br>
<br>
Check out Wikipedia on the subjects of polymorphism and duck-typing,
though the articles are a bit too academic for my taste - and I'm a
teacher!<br>
<br>
If you wanted to, you might submit a HashArgConstraint class as a
possible patch to <tt>lib/specs/mocks/argument_epectation.rb</tt>.
This would 'know' that it would receive an array of arrays and adjust
its expectation accordingly. Or have I just slipped into teaching mode
again? Sorry.<br>
</body>
</html>