<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Floehopper: Tell Don't Ask</title>
    <link>http://blog.floehopper.org/articles/2006/12/23/tell-dont-ask</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>thoughts on the bergy bits of life</description>
    <item>
      <title>Tell Don't Ask</title>
      <description>&lt;p&gt;Following on from a couple of my &lt;a href="http://blog.floehopper.org/articles/2006/12/23/fixtures-mock-objects-or-in-memory-activerecord-objects"&gt;previous&lt;/a&gt; &lt;a href="http://blog.floehopper.org/articles/2006/12/23/stub-queries-and-expect-commands"&gt;posts&lt;/a&gt;, here are some more comments on the &lt;a href="http://metaclass.org/2006/12/22/making-a-mockery-of-activerecord"&gt;Making a Mockery of ActiveRecord&lt;/a&gt; article&amp;#8230;&lt;/p&gt;


	&lt;p&gt;Something that may be adding unnecessary complexity to the test is that the &lt;code&gt;Message#generate&lt;/code&gt; method knows the structure of objects for which it does not have direct references. For example, it looks like the &lt;code&gt;List&lt;/code&gt; and &lt;code&gt;Person&lt;/code&gt; instances are supplied, just so that the &lt;code&gt;generate&lt;/code&gt; method can navigate to the &lt;code&gt;subscriptions&lt;/code&gt; in order to call &lt;code&gt;create&lt;/code&gt;. This breaks the &lt;a href="http://en.wikipedia.org/wiki/Law_of_Demeter"&gt;Law of Demeter&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;A first step to improving the design would be to have a &lt;code&gt;List#create_subscriptions&lt;/code&gt; method which would be called by &lt;code&gt;Message#generate&lt;/code&gt;. We could then simplify the unit test as follows&amp;#8230;&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;test_should_create_email_messages_and_subscriptions_when_include_subscribers_is_true&lt;/span&gt;
    &lt;span class="ident"&gt;list&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;mock&lt;/span&gt;&lt;span class="punct"&gt;()&lt;/span&gt;
    &lt;span class="ident"&gt;campaign&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Campaign&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:people&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;[])&lt;/span&gt;
    &lt;span class="ident"&gt;message&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Message&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;new&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:campaign&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ident"&gt;campaign&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
    &lt;span class="ident"&gt;message&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;stubs&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:lists&lt;/span&gt;&lt;span class="punct"&gt;).&lt;/span&gt;&lt;span class="ident"&gt;returns&lt;/span&gt;&lt;span class="punct"&gt;([&lt;/span&gt;&lt;span class="ident"&gt;list&lt;/span&gt;&lt;span class="punct"&gt;])&lt;/span&gt;
    &lt;span class="ident"&gt;message&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;include_subscribers&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;true&lt;/span&gt;

    &lt;span class="ident"&gt;list&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;expects&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="symbol"&gt;:create_subscriptions&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;

    &lt;span class="ident"&gt;message&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;generate&lt;/span&gt;
    &lt;span class="ident"&gt;assert_equal&lt;/span&gt; &lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;message&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;email_messages&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Obviously we&amp;#8217;d need to add a separate unit test for the &lt;code&gt;List#create_subscriptions&lt;/code&gt; method, but that would also be much simpler and easier to understand. In this way we have decoupled &lt;code&gt;Message&lt;/code&gt; from the structure of &lt;code&gt;List&lt;/code&gt; and are just relying on its behaviour. &lt;a href="http://nat.truemesh.com/"&gt;Nat Pryce&lt;/a&gt; &amp;#38; &lt;a href="http://stevef.truemesh.com/"&gt;Steve Freeman&lt;/a&gt; call this the &lt;a href="http://www.mockobjects.com/2006/10/tell-dont-ask-and-mock-objects.html"&gt;&lt;cite&gt;Tell Don&amp;#8217;t Ask&lt;/cite&gt; style&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Finally, I prefer not to have much more than &lt;a href="http://www.artima.com/weblogs/viewpost.jsp?thread=35578"&gt;one assertion per test&lt;/a&gt; (and don&amp;#8217;t forget verifying an expectation is effectively an assertion), so I&amp;#8217;d probably split the test into two &amp;#8211; one to verify &lt;code&gt;create_subscriptions&lt;/code&gt; was called and one to check the &lt;code&gt;email_messages&lt;/code&gt; were created.&lt;/p&gt;</description>
      <pubDate>Sat, 23 Dec 2006 20:04:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:8d4b111a-ca8d-47a5-af8c-bc98612f7aa2</guid>
      <author>James Mead</author>
      <link>http://blog.floehopper.org/articles/2006/12/23/tell-dont-ask</link>
      <category>tell</category>
      <category>ask</category>
      <category>law</category>
      <category>demeter</category>
      <category>mock</category>
      <category>ruby</category>
      <category>test</category>
    </item>
    <item>
      <title>"Tell Don't Ask" by James Mead</title>
      <description>&lt;p&gt;Cool.&lt;/p&gt;</description>
      <pubDate>Wed, 27 Dec 2006 03:33:53 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:92c9b8b8-05d4-430a-a1bd-c465a5d8592f</guid>
      <link>http://blog.floehopper.org/articles/2006/12/23/tell-dont-ask#comment-142</link>
    </item>
    <item>
      <title>"Tell Don't Ask" by Wilson Bilkovich</title>
      <description>&lt;p&gt;So, based on your points, I have refactored the code.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://pastie.caboo.se/29672"&gt;It is now about 6 jillion times easier to test&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Tue, 26 Dec 2006 23:38:57 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:a714cf44-7c6f-48ec-b499-5198ed389fbf</guid>
      <link>http://blog.floehopper.org/articles/2006/12/23/tell-dont-ask#comment-141</link>
    </item>
    <item>
      <title>"Tell Don't Ask" by David Chelimsky</title>
      <description>&lt;p&gt;This is one of the big pitfalls in rails apps. AR makes it way to easy to violate TDA and LoD. Thanks for pointing this out. Please keep doing so &amp;#8211; we all need to be chanting this like a mantra.&lt;/p&gt;</description>
      <pubDate>Tue, 26 Dec 2006 08:12:48 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:e89cae59-3eca-41b4-9408-8c0a41940bfd</guid>
      <link>http://blog.floehopper.org/articles/2006/12/23/tell-dont-ask#comment-140</link>
    </item>
    <item>
      <title>"Tell Don't Ask" by Wilson Bilkovich</title>
      <description>&lt;p&gt;No way. Game on.
Merry Christmas. :)&lt;/p&gt;</description>
      <pubDate>Sun, 24 Dec 2006 22:28:30 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:00d3f0ba-aff6-4f97-b37c-f15b2485c9cc</guid>
      <link>http://blog.floehopper.org/articles/2006/12/23/tell-dont-ask#comment-133</link>
    </item>
    <item>
      <title>"Tell Don't Ask" by James Mead</title>
      <description>&lt;p&gt;Channing: Thanks for the reference to the Tell Don&amp;#8217;t Ask principle. I know less than you about its origins.&lt;/p&gt;


	&lt;p&gt;Wilson: Thanks for your comment &amp;#8211; it is helpful to see the code under test. I&amp;#8217;m sorry I went a bit overboard by posting so much about your article, but I found the exercise helpful in getting some things straight in my own head. I hope you&amp;#8217;re not offended.&lt;/p&gt;</description>
      <pubDate>Sun, 24 Dec 2006 16:31:20 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:5b905816-4065-41ac-8584-224a64281808</guid>
      <link>http://blog.floehopper.org/articles/2006/12/23/tell-dont-ask#comment-132</link>
    </item>
    <item>
      <title>"Tell Don't Ask" by Wilson Bilkovich</title>
      <description>&lt;p&gt;Interesting. Thanks for thinking so much about my article. I wrote it partly to help me think about whether I was going about things the right way.&lt;/p&gt;


	&lt;p&gt;There are definitely some rough edges in AR where things are passed by &amp;#8216;dup&amp;#8217;ing, rather than by reference. Pays to keep that in mind.&lt;/p&gt;


	&lt;p&gt;Just in case it helps, &lt;a href="http://pastie.caboo.se/29478"&gt;here&amp;#8217;s the implementation&lt;/a&gt; that is being spec&amp;#8217;d out:&lt;/p&gt;


	&lt;p&gt;You&amp;#8217;re right that the Association Proxy setup in ActiveRecord makes it hard to obey the law of demeter.&lt;/p&gt;</description>
      <pubDate>Sun, 24 Dec 2006 10:43:44 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:442be7bd-d8ec-4516-ad21-3f646aacc3fb</guid>
      <link>http://blog.floehopper.org/articles/2006/12/23/tell-dont-ask#comment-130</link>
    </item>
    <item>
      <title>"Tell Don't Ask" by Channing Walton</title>
      <description>&lt;p&gt;The first time I can find that the Tell Don&amp;#8217;t Ask principle is mentioned is in the &lt;a href="http://www.pragmaticprogrammer.com/ppllc/papers/1998_05.html"&gt;Pragmatic Programmer&amp;#8217;s article in 1998&lt;/a&gt;. They seem to credit the idea to Alec Sharp in his book Smalltalk by Example (1997).&lt;/p&gt;


	&lt;p&gt;Anyone know of any older references to this principle?&lt;/p&gt;</description>
      <pubDate>Sun, 24 Dec 2006 05:37:15 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:64c795e0-4dc4-487b-925d-fdad6decbb3d</guid>
      <link>http://blog.floehopper.org/articles/2006/12/23/tell-dont-ask#comment-129</link>
    </item>
    <item>
      <title>"Tell Don't Ask" by Luke Redpath</title>
      <description>&lt;p&gt;Thinking about it, the assertion of the number of email messages looks like it would belong in the create_subscriptions test as the creation of email messages is part of its behaviour&lt;/p&gt;</description>
      <pubDate>Sat, 23 Dec 2006 21:54:50 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:c75cce51-8706-4ff0-9eac-14fa114c85cf</guid>
      <link>http://blog.floehopper.org/articles/2006/12/23/tell-dont-ask#comment-128</link>
    </item>
  </channel>
</rss>
