<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" version="2.0">
  <channel>
    <title>No Fluff Just Stuff</title>
    <link>http://www.groovygrails.com</link>
    <description>The best value in the Java/Open Source conferencing space hands down</description>
    <item>
      <title>Podcast on Pulse in education and training</title>
      <link>http://www.groovygrails.com/blog/kenneth_kousen/2008/08/podcast_on_pulse_in_education_and_training.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>&lt;div class='snap_preview'&gt;&lt;br /&gt;&lt;p&gt;A couple of weeks ago I participated in a BriefingsDirect podcast about using &lt;a href="http://www.poweredbypulse.com/"&gt;Pulse&lt;/a&gt; in academic and training environments.  For those who aren&amp;#8217;t aware, &lt;a href="http://www.poweredbypulse.com/"&gt;Pulse&lt;/a&gt; is a product created by &lt;a href="http://www.genuitec.com/"&gt;Genuitec&lt;/a&gt; (the same people who make the &lt;a href="http://www.myeclipseide.com/"&gt;MyEclipse IDE&lt;/a&gt;) that allows you to manage Eclipse profiles and plugins.  I&amp;#8217;ve used MyEclipse in my academic courses at &lt;a href="http://www.ewp.rpi.edu/hartford/"&gt;Rensselaer at Hartford&lt;/a&gt; for several years, so they asked me to be on the podcast.&lt;/p&gt;
&lt;p&gt;The other people on the podcast were &lt;a href="http://www.redmonk.com/cote/"&gt;Michael Cote&lt;/a&gt;, an analyst with &lt;a href="http://redmonk.com/"&gt;RedMonk&lt;/a&gt;, and &lt;a href="http://www.genuitec.com/about/leadership.html"&gt;Todd Williams&lt;/a&gt;, VP of Technology for Genuitec.  The podcast was hosted by Dana Gardner, principal analyst at &lt;a href="http://www.interarbor-solutions.com/"&gt;Interarbor Solution&lt;/a&gt;s.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://interarbor.libsyn.com/index.php?post_id=370535"&gt;The podcast itself&lt;/a&gt; and &lt;a href="http://briefingsdirect.blogspot.com/2008/08/pulse-provides-novel-training-and-tools.html"&gt;a verbatim transcript&lt;/a&gt; are now available, and can be found &lt;a href="http://briefingsdirect.blogspot.com/2008/08/pulse-provides-novel-training-and-tools.html"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This was my first time being interviewed on a podcast, and it was quite an experience.  I would say that it was an &lt;em&gt;interesting &lt;/em&gt;experience, but one of the most obvious things that jumps out at me from reading the transcript is that I use the word &amp;#8220;interesting&amp;#8221; far too often. &lt;img src='http://s.wordpress.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /&gt;&lt;/p&gt;
&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/kousenit.wordpress.com/133/" /&gt; &lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/kousenit.wordpress.com/133/" /&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/kousenit.wordpress.com/133/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/kousenit.wordpress.com/133/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/kousenit.wordpress.com/133/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/kousenit.wordpress.com/133/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/kousenit.wordpress.com/133/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/kousenit.wordpress.com/133/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/kousenit.wordpress.com/133/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/kousenit.wordpress.com/133/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/kousenit.wordpress.com/133/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/kousenit.wordpress.com/133/" /&gt;&lt;/a&gt; &lt;img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=kousenit.wordpress.com&amp;blog=186706&amp;post=133&amp;subd=kousenit&amp;ref=&amp;feed=1" /&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 21 Aug 2008 13:00:02 CDT</pubDate>
      <guid isPermaLink="true">http://kousenit.wordpress.com/?p=133</guid>
      <dc:creator>Kenneth Kousen</dc:creator>
    </item>
    <item>
      <title>Top 5 reasons why Out Of Office messages are wrong</title>
      <link>http://www.groovygrails.com/blog/emmanuel_bernard/2008/08/top_5_reasons_why_out_of_office_messages_are_wrong.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description />
      <pubDate>Thu, 21 Aug 2008 11:00:02 CDT</pubDate>
      <guid isPermaLink="true">tag:blogger.com,1999:blog-2238439969300766358.post-2675656545027174778</guid>
      <dc:creator>Emmanuel Bernard</dc:creator>
    </item>
    <item>
      <title>Grails Training - Aug. 26 - 28, 2008</title>
      <link>http://www.groovygrails.com/conference/chicago/2008/08/index.html?utm_source=showWeeks8&amp;utm_medium=rss&amp;utm_campaign=showrss</link>
      <description>&lt;div style="font-family: Arial, Verdana, Helvetica, sans-serif; font-size: 10pt;"&gt;&#xD;
&#xD;
&lt;p&gt;&#xD;
No Fluff Just Stuff is pleased to announce the &lt;a style="color: #336699; text-decoration: none;" href="http://www.groovygrails.com/show_view.jsp?showId=174&amp;utm_source=showWeeks8&amp;utm_medium=rss&amp;utm_campaign=showrss" target="new"&gt;Grails Training&lt;/a&gt;, Aug. 26 - 28, 2008.&#xD;
&lt;/p&gt;&#xD;
&#xD;
	&lt;div style="background-color: #0860A9; color: #EFCE52; font-weight: bold; padding: 5px 5px 5px 5px;"&gt;&#xD;
		&lt;em&gt;Catch these Featured Sessions&lt;/em&gt;&#xD;
	&lt;/div&gt;&#xD;
&#xD;
	&lt;div style="border: 1px solid #999999; padding: 0 5px 0 5px;"&gt;&#xD;
&#xD;
	&lt;table cellpadding="0" cellspacing="0" style="font-size: 10pt;"&gt;&#xD;
&#xD;
	&#xD;
	&lt;/table&gt;&#xD;
&#xD;
	&lt;/div&gt;&#xD;
&#xD;
&lt;/div&gt;</description>
      <pubDate>Thu, 21 Aug 2008 09:00:00 CDT</pubDate>
      <guid isPermaLink="true">http://www.groovygrails.com/conference/chicago/2008/08/index.html</guid>
    </item>
    <item>
      <title>Essence vs. Ceremony Pop Quiz</title>
      <link>http://www.groovygrails.com/blog/stuart_halloway/2008/08/essence_vs_ceremony_pop_quiz.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>&lt;p&gt;&lt;a href="http://nealford.com/mypastconferences.htm"&gt;Neal&lt;/a&gt; and I have been talking a lot about &lt;a href="http://blog.thinkrelevance.com/2008/4/1/ending-legacy-code-in-our-lifetime"&gt;Essence vs. Ceremony&lt;/a&gt; &lt;a href="http://rubynation.org/speakers"&gt;this&lt;/a&gt; &lt;a href="http://www.erubycon.com/"&gt;summer&lt;/a&gt;. In most of the examples I give, it is easy to tell &lt;a href="http://blog.thinkrelevance.com/2008/4/23/refactoring-from-ceremony-to-essence"&gt;which is which&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But that isn't always true. Consider &lt;a href="http://scala-blogs.org/2008/07/application-trait-considered-harmful.html"&gt;this example&lt;/a&gt; from Scala. Does the application trait improve essence, or lead to more ceremony? I will post my answer next week.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/relevance-llc/~4/370867356" height="1" width="1"/&gt;</description>
      <pubDate>Thu, 21 Aug 2008 08:00:02 CDT</pubDate>
      <guid isPermaLink="true">tag:blog.thinkrelevance.com,2008-08-21:10070</guid>
      <dc:creator>Stuart Halloway</dc:creator>
    </item>
    <item>
      <title>Rotor v2 book draft available</title>
      <link>http://www.groovygrails.com/blog/ted_neward/2008/08/rotor_v2_book_draft_available.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>&lt;p&gt;
&lt;a href="http://callvirt.net/blog/entry.aspx?entryid=b9a94d0c-761a-4d6b-bc2f-d6a5f8c1a4a7"&gt;As
Joel points out&lt;/a&gt;, we've made a draft of the &lt;em&gt;SSCLI 2.0 Internals&lt;/em&gt; book available
for download (via his blog). Rather than tell you all about the book, which Joel summarizes
quite well, instead I thought I'd tell you about the process by which the book came
to be.
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
&lt;em&gt;Editor's note: if you have no interest in the process by which a book can get
done, skip the rest of this blog entry.&lt;/em&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
One thing that readers will note that's different about this version of "the Rotor
book" is that it's &lt;em&gt;not&lt;/em&gt; being done through one of the traditional publishers.
This is deliberate. As Joel and I talk about on the &lt;a href="http://www.dotnetrocks.com/default.aspx?showNum=360"&gt;.NET
Rocks! show we did together&lt;/a&gt;, the first Rotor book was on the first version of
Rotor, which shipped shortly after the .NET 1.1 bits shipped to customers. That was
back in the summer of 2001. Dave, Geoff and I shipped the book, I did a few conference
talks on Rotor for the relatively few people who had an interest in what was going
on "under the hood" of the CLR, and then we all sort of parted ways. (Dave retired
from Microsoft entirely shortly thereafter, in order "to focus on the two things that
matter in life: making music and making wine", as he put it.) Mission accomplished,
we moved on.
&lt;/p&gt;
&lt;p&gt;
Meanwhile, as we all knew would happen, the world moved on--Whidbey (.NET 2.0) shipped,
and with it came a whole slew of CLR enhancements, most notably generics. Unlike how
generics happened in the JVM, CLR generics are carried through all the way to the
type system, and as a result, a lot of what we said in the first Rotor book was instantly
rendered obsolete. Granted, one could always grab the Gyro patch for Rotor and see
what generics would have looked like, but even that was pretty much rendered obsolete
by the emergence of the SSCLI 2.0 drop, bringing the Rotor code up to date with the
Whidbey production CLR release.
&lt;/p&gt;
&lt;p&gt;
Except the book was, to be blunt about it, left behind.
&lt;/p&gt;
&lt;p&gt;
Speaking honestly, the book never broke any sales records. Sure, for a while there
it was the #1 best-selling book (in Redmond, WA, to my &lt;em&gt;total&lt;/em&gt; shock and surprise)
on Amazon, but we never had the kind of best-seller success that that of, say, &lt;em&gt;Programming
Ruby&lt;/em&gt; or pick-your-favorite-ASP.NET book. In the book publishing world, this was
kind of the moral equivalent to watching your neighbors' slide show of their vacation:
boring for most people &lt;em&gt;not&lt;/em&gt; in the pictures, unless you were &lt;em&gt;really&lt;/em&gt; interested
in either the place they were visiting or what they did there. Most of our audience
were either people working on the CLR itself (hence all the copies sold in Redmond,
get it?), people who were researching on the CLR (such as the various Rotor research
projects that came over a few years after its release), or people who just had that
itch to "get wonky with it" and learn how some of the structures worked. Granted,
a lot of what those people in the last category learned turned out to be pretty helpful
in the Real World, but it was a payoff that came with a pretty non-trivial learning
curve.
&lt;/p&gt;
&lt;p&gt;
Fast-forward a few years, to the end of calendar year 2005.
&lt;/p&gt;
&lt;p&gt;
By this point, .NET 2.0 has been out in production form for a bit, and Mark Lewin,
then of Microsoft University Relations (I think that was his job, but to be honest
my recollection on that point is kinda fuzzy) approached me: Microsoft was interested
in seeing a second edition of the book out, to keep the Rotor community up to date
with what was going on in the state of the art in the CLR. Was I interested? Sure,
but the rules surrounding a multi-author book and subsequent editions are pretty clear:
everybody has to be given right of first refusal. Thus a two-fold task was under way:
find a co-author (preferably somebody from the CLR team, since my skills had never
really been in navigating the Rotor source code in the first place, and I hadn't really
spent a significant amount of time in the code since 2001), and get Geoff and Dave
to indicate--in a very proper legal fashion--that they were passing on the second
edition.
&lt;/p&gt;
&lt;p&gt;
Ugh. Lawyers. Contracts. Bleah.
&lt;/p&gt;
&lt;p&gt;
John Osborn then broke the bad news: OReilly wasn't interested in doing a second edition.
I couldn't really blame them, since the first hadn't broken any kind of sales record,
but I was a bit bummed because I thought this was the end of the road.
&lt;/p&gt;
&lt;p&gt;
Mark Lewin to the rescue. Apparently his part of Microsoft &lt;em&gt;really&lt;/em&gt; wanted
this book out, to the point where they were willing to fund the effort, if I and my
co-author were still interested. Sure, that sounded like a workable idea. And once
the book was done, maybe we could publish it through MSPress, if that sounded like
a good idea to me. Sure, that sounded good. Then Mark dropped the suggestion that
maybe I could talk to Joel Pobar, former CLR geek extraordinaire, to see if he was
interested. Joel had impressed me back when we'd briefly touched bases during the
first book-writing experience, so yeah, sure, that sounded like a good idea. He was
on board pretty quickly, and so we had the first step out of the way.
&lt;/p&gt;
&lt;p&gt;
Next, we had to get OReilly to release their copyright on the first book, so we (and
possibly MSPress) could work on and publish the second edition. This turned out to
be a huge part of the time between then and now, not owing to any one party's deliberate
attempt to derail the process, but just because copies of contracts had to be sent
to the original three authors (myself, Stutz and Geoff) to sign over our rights with
OReilly to a Creative Commons License, then copies had to be sent to everybody else
so all the signatures could appear on one document, and so on.
&lt;/p&gt;
&lt;p&gt;
Did I say it already? Ugh. Lawyers. Contracts. Bleah.
&lt;/p&gt;
&lt;p&gt;
Then, we had to get a contract from Microsoft signed, and that meant more contracts
flying back and forth across the fax lines, and then later the US (and Australian)
postal system, and that was more delays as the same round of signatures had to be
exchanged.
&lt;/p&gt;
&lt;p&gt;
Just for the record: Ugh. Lawyers. Contracts. Bleah.
&lt;/p&gt;
&lt;p&gt;
Finally, though, the die was cast, the authors were ready to go, and.... Hey, does
anybody have the latest soft copy of the Word docs we used from the first edition?
A quick email to John (Osborn) took longer than we thought, as OReilly tried to find
the post-QA docs for us to work from. (I had my own copies, of course, but they were
pre-QA, and thus not really what we wanted to start from.) More rounds of emails to
try and track those down, so we can get started. Oh, and while we're at it, can we
get the figures/graphics, too? They're not in the manuscript directly, so.... Oh,
wait, does anybody know how to read .EPS files?
&lt;/p&gt;
&lt;p&gt;
Then began the actual writing process, or, to be more precise, the revision process.
We decided on a process similar to the way the first book had been written: Joel,
being the "subject matter expert", would take a first pass on the text, and sketch
in the rough outlines of what needed to be said. I would then take the prose, polish
it up (which in many cases didn't require a whole lot of work, Joel being a great
writer in his own right) and rearrange sections as necessary to make it flow more
easily, as well as flesh out certain sections that didn't require a former position
on the CLR team to write. Joel would then have a look at what I wrote, and assuming
I didn't get it completely wrong, would sign off on it, and the chapter/section/paragraph/whatever
was done.
&lt;/p&gt;
&lt;p&gt;
And now we're in the process of doing that cosmetic cleanup that's part of the overtime
period in book-writing, including generating the table of contents and index, since,
it turns out, we'd rather publish it ourselves than through MSPress (which they're
OK with). So, readers will have a choice: get the free download from Microsoft's website
(once we're done, which should be "real soon now") and read it in soft-copy, or buy
it off of Amazon in "treeware version", which will put a modest amount of money into
Joel's and my collective pocket (once the relatively modest expenses of self-publishing
are covered, that is).
&lt;/p&gt;
&lt;p&gt;
This will be my first experience with self-publishing (as it is for Joel, too), so
I'm eager to see how the whole things turns out. One thing I will warn the prospective
self-publisher, though: do &lt;em&gt;not&lt;/em&gt; underestimate the time you will spend doing
those things the editorial/QA/copyedit pass normally handles for you, because it's
kind of a pain in the *ss to do it yourself. Still, it's worth it, particularly if
you're having a hard time selling your book to a publisher who, for reasons of economy
of scale, don't want to publish a niche book (like this one).
&lt;/p&gt;
&lt;p&gt;
Anyway, like many of my blog postings, this post has gone on long enough, so I'll
sign off here with a "go read the draft", even if you're a Java or other execution
engine/virtual machine kind of developer--seeing the nuts and bolts of a complex execution
engine in action is a pretty cool exercise.
&lt;/p&gt;
&lt;p&gt;
Oh, and if anybody's interested in doing a similar kind of effort around the OpenJDK
(once it ships), let me know, 'cuz I'm a glutton for punishment....
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=033a0895-7246-4015-8516-fa26291adc45" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
      <pubDate>Wed, 20 Aug 2008 16:00:02 CDT</pubDate>
      <guid isPermaLink="true">http://blogs.tedneward.com/PermaLink,guid,033a0895-7246-4015-8516-fa26291adc45.aspx</guid>
      <dc:creator>Ted Neward</dc:creator>
    </item>
    <item>
      <title>Ajax running on borrowed time</title>
      <link>http://www.groovygrails.com/blog/richard_monson-haefel/2008/08/ajax_running_on_borrowed_time.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_HOfY71whEUc/SKxLDzivkHI/AAAAAAAAAHM/6zb0OCF2NpU/s1600-h/ajax_dinosaur.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://1.bp.blogspot.com/_HOfY71whEUc/SKxLDzivkHI/AAAAAAAAAHM/6zb0OCF2NpU/s320/ajax_dinosaur.jpg" alt="" id="BLOGGER_PHOTO_ID_5236642995472666738" border="0" /&gt;&lt;/a&gt;&lt;a href="http://www.erikbianchi.com/"&gt;From erikbianchi.com&lt;/a&gt;: "JavaScript has remained virtually unchanged for over a decade now and with ECMA’s recent announcement, about dropping the ECMAScript 4 proposal, JavaScript will continue to remain essentially the same for at least another 5 years."</description>
      <pubDate>Wed, 20 Aug 2008 13:00:02 CDT</pubDate>
      <guid isPermaLink="true">tag:blogger.com,1999:blog-7867849070722123199.post-2518335704375774066</guid>
      <dc:creator>Richard Monson-Haefel</dc:creator>
    </item>
    <item>
      <title>An Attempt to Define Value</title>
      <link>http://www.groovygrails.com/blog/johanna_rothman/2008/08/an_attempt_to_define_value.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>&lt;p&gt;Jim, in his comment on  &lt;a href="http://jrothman.com/blog/mpd/2008/08/intution-is-not-enough-for-knowing-about-the-project-portfolio.html" target="_blank"&gt;Intuition is Not Enough for Knowing About the Project Portfolio,&lt;/a&gt; said:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;I am having trouble with the definition of the word “value” in this context. Do you mean showing progress, as in earned value, or value to the customer, such as in ROI or payback period? Value has become a loaded word. Please define your terms.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;To me, value is some visible form of progress. I prefer working product. I can live with a demo. I can live with a prototype. In some very small number of organizations, I can briefly live with a document. A document ceases to be visible progress after a very small period of time, such as a few days, maybe a week. Demos and prototypes also lose their value over time, if they do not become working product.&lt;/p&gt;
&lt;p&gt;Managers can&amp;#8217;t make good decisions about the portfolio if they can&amp;#8217;t see visible progress, so they can tell if the money they&amp;#8217;ve spent is worth the time they&amp;#8217;ve invested.&lt;/p&gt;
&lt;p&gt;If I really knew how to calculate ROI (and not make it be a number I can just make work), I would use ROI. But that&amp;#8217;s a bigger rant for another time.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/ManagingProductDevelopment?a=kodsIK"&gt;&lt;img src="http://feeds.feedburner.com/~f/ManagingProductDevelopment?i=kodsIK" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ManagingProductDevelopment?a=yqiXYK"&gt;&lt;img src="http://feeds.feedburner.com/~f/ManagingProductDevelopment?i=yqiXYK" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ManagingProductDevelopment?a=suCxuk"&gt;&lt;img src="http://feeds.feedburner.com/~f/ManagingProductDevelopment?i=suCxuk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ManagingProductDevelopment?a=gzkoIk"&gt;&lt;img src="http://feeds.feedburner.com/~f/ManagingProductDevelopment?i=gzkoIk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ManagingProductDevelopment?a=694FtK"&gt;&lt;img src="http://feeds.feedburner.com/~f/ManagingProductDevelopment?i=694FtK" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ManagingProductDevelopment?a=ab42mK"&gt;&lt;img src="http://feeds.feedburner.com/~f/ManagingProductDevelopment?i=ab42mK" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ManagingProductDevelopment/~4/369980294" height="1" width="1"/&gt;</description>
      <pubDate>Wed, 20 Aug 2008 11:00:02 CDT</pubDate>
      <guid isPermaLink="true">http://jrothman.com/blog/mpd/?p=8477</guid>
      <dc:creator>Johanna Rothman</dc:creator>
    </item>
    <item>
      <title>Taking SwingBuilder's binding for a spin</title>
      <link>http://www.groovygrails.com/blog/andres_almiray/2008/08/taking_swingbuilder_s_binding_for_a_spin.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>Those of you that follow &lt;a href="http://twitter.com/shemnon"&gt;@shemnnon&lt;/a&gt;'s &lt;a href="http://shemnon.com/speling/"&gt;blog&lt;/a&gt; will surely know that he has revamped how binding is supported in the development versions of Groovy 1.6.x (&lt;a href="http://shemnon.com/speling/2008/04/bindable-observable-properties.html"&gt;here&lt;/a&gt;, &lt;a href="http://shemnon.com/speling/2008/05/greet-a-groovy-twitter-client.html"&gt;here&lt;/a&gt; and &lt;a href="http://shemnon.com/speling/2008/06/more-than-i-wanted-to-know-abo-1.html"&gt;here&lt;/a&gt;). Impatiently as ever, I created my own distro of groovy 1.6-beta-2-SNAPSHOT and gave it a try, quite fitting with the latest JavaFx Script experiments.&lt;br/&gt;&lt;br/&gt;One of the appealing features of JavaFx Script is that it has binding baked right into the language, it also sports the notion of triggers. You can attach any function on a trigger, whenever the trigger receives a biding update event the function will be called. This is akin to PropertyChangeListener and PropertyChangeEvent, only you don't see those classes in the open with JavaFx. So here goes, three simple binding/triggers examples on JavaFx Script and Groovy. The examples are not comprehensive, binding both languages can cover a broader spectrum. It is important to note that binding in Groovy is provided by a set of APIs (SwingBuilder and the bind factory) not by the language itself.&lt;br/&gt;&lt;br/&gt;The first snippet exemplifies binding between two components, the label's text will be updated every time text is written on the textField, first comes the JavaFx Script version&lt;br/&gt;&lt;textarea name="srccode" class="jfx:nocontrols:nogutter" cols="80" rows="20"&gt;import javafx.ext.swing.*;
import java.lang.System;

var textField = SwingTextField { }
var label = Label {
   text: bind textField.text
}

SwingFrame {
   title: 'Binding Example (JavaFx)'
   visible: true
   closeAction: function(){ System.exit(0); }
   width: 240
   height: 100
   content: GridPanel {
      columns: 1
      rows: 2
      content: [ textField, label ]
   }
}&lt;/textarea&gt;And now its Groovy counterpart&lt;br/&gt;&lt;textarea name="srccode" class="groovy:nocontrols:nogutter" cols="80" rows="12"&gt;import groovy.swing.SwingBuilder
import static javax.swing.JFrame.EXIT_ON_CLOSE

SwingBuilder.build {
   lookAndFeel( 'nimbus' )
   frame( title: 'Binding Example (Groovy)', size: [240,100], show: true,
          locationRelativeTo: null, defaultCloseOperation: EXIT_ON_CLOSE ) {
      gridLayout( cols: 1, rows: 2 ) 
      textField( id: 'textField' )
      label( text: bind{ textField.text } )
   }
}&lt;/textarea&gt;&lt;br/&gt;Maybe there is another way to setup the binding between the label and the textfield on JavaFx Script, but you can't define variables while building the content unless you do it inside a function, this means that those components are not built close to the place where they are inserted into the UI hierarchy. Clearly that is not a problem with the Groovy version. The next snippet introduces one level of indirection, a textModel. Now the label will bind to a third object that holds a text attribute. A button is also added to 'trigger' the update&lt;br/&gt;&lt;textarea name="srccode" class="jfx:nocontrols:nogutter" cols="80" rows="30"&gt;import javafx.ext.swing.*;
import java.lang.System;

class TextModel {
   public attribute text:String;
}

var textModel = TextModel { }
var textField = SwingTextField { }
var label = Label { text: bind textModel.text }

var button = SwingButton {
   text: 'Update'
   action: function(): Void {
      textModel.text = textField.text
   }
}

SwingFrame {
   title: 'Binding Example (JavaFx)'
   visible: true
   closeAction: function(){ System.exit(0); }
   width: 240
   height: 100
   content: GridPanel {
      columns: 1
      rows: 3
      content: [ textField, label, button ]
   }
}&lt;/textarea&gt;The code is pretty much self explanatory, I would say the same holds true for the Groovy version&lt;textarea name="srccode" class="groovy:nocontrols:nogutter" cols="80" rows="15"&gt;import groovy.swing.SwingBuilder
import static javax.swing.JFrame.EXIT_ON_CLOSE

def textModel = [text: ''] as ObservableMap

SwingBuilder.build {
   lookAndFeel( 'nimbus' )
   frame( title: 'Binding Example (Groovy)', size: [240,100], show: true,
          locationRelativeTo: null, defaultCloseOperation: EXIT_ON_CLOSE ) {
      gridLayout( cols: 1, rows: 3 ) 
      textField( id: 'textField' )
      label( text: bind{ textModel.text } )
      button( 'Update', actionPerformed: { textModel.text = textField.text } )
   }
}&lt;/textarea&gt;ObservableMap is an utility class that fires up PropertyChangeEvents every time a property is added, updated and/or removed from it, in contrast observable beans usually fire events when a property is updated only (more options for you!). I can hear someone at the back saying 'but you JavaFx Script &lt;i&gt;does&lt;/i&gt; have triggers, why don't you use them instead?' certainly I will. So let's remove the button and bind the label, textField and textModel, adding a console printout just to show that the model is being updated as expected, and it in turn updates the label&lt;textarea name="srccode" class="jfx:nocontrols:nogutter" cols="80" rows="25"&gt;import javafx.ext.swing.*;
import java.lang.System;

class TextModel {
   public attribute text:String on replace {
      System.out.println(text);
   };
}

var textField = SwingTextField { }
var textModel = TextModel { text: bind textField.text }
var label = Label { text: bind textModel.text }

SwingFrame {
   title: 'Binding Example (JavaFx)'
   visible: true
   closeAction: function(){ System.exit(0); }
   width: 240
   height: 100
   content: GridPanel {
      columns: 1
      rows: 2
      content: [ textField, label ]
   }
}&lt;/textarea&gt;It only took two binding calls and one trigger, sweet. What about the Groovy version? well, we don't have triggers (yet) that make the code short but it is certainly doable&lt;textarea name="srccode" class="groovy:nocontrols:nogutter" cols="80" rows="20"&gt;import groovy.swing.SwingBuilder
import java.beans.PropertyChangeListener
import static javax.swing.JFrame.EXIT_ON_CLOSE

def textModel = [text: ''] as ObservableMap
textModel.addPropertyChangeListener({ evt -&gt;
   println evt.newValue
} as PropertyChangeListener)

SwingBuilder.build {
   lookAndFeel( 'nimbus' )
   frame( title: 'Binding Example (Groovy)', size: [240,100], show: true,
          locationRelativeTo: null, defaultCloseOperation: EXIT_ON_CLOSE ) {
      gridLayout( cols: 1, rows: 2 ) 
      textField( id: 'textField' )
      bind( source: textField, sourceProperty: 'text', 
            target: textModel, targetProperty: 'text' )
      label( text: bind{ textModel.text } )
   }
}&lt;/textarea&gt;Notice that a regular PropertyChangeListener has been registered with the ObservableMap, this is how triggers are implemente in Java/Groovy. Binding the textField's text to the textModel's text property is also a bit more verbose than before. As a matter of fact that syntax used to be the previous one, so you can see that binding has been improved, just a bit but good enough &lt;img src="http://www.jroller.com/images/smileys/grin.gif" class="smiley" alt=":-D" title=":-D" /&gt; I think it is possible to cook up a trigger dsl to reduce the amount of code required to create triggers in Groovy, don't you think? we have metaprogramming on our side after all.&lt;br/&gt;&lt;br/&gt;Keep on Groovying!</description>
      <pubDate>Wed, 20 Aug 2008 08:00:02 CDT</pubDate>
      <guid isPermaLink="true">http://www.jroller.com/aalmiray/entry/taking_swingbuilder_s_binding_for</guid>
      <dc:creator>Andres Almiray</dc:creator>
    </item>
    <item>
      <title>Compass 2.0.2 Released</title>
      <link>http://www.groovygrails.com/blog/shay_banon/2008/08/compass_2_0_2_released.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>&lt;p&gt;&lt;a href="http://www.compass-project.org"&gt;Compass&lt;/a&gt; version 2.0.2 released. This is a bug fix released for Compass 2.0 and is recommended for all Compass users. Full change log can be found &lt;a href="http://issues.compass-project.org/secure/ReleaseNote.jspa?projectId=10000&amp;#038;styleName=Html&amp;#038;version=10134"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/kimchyblog/~4/369289695" height="1" width="1"/&gt;</description>
      <pubDate>Tue, 19 Aug 2008 16:00:02 CDT</pubDate>
      <guid isPermaLink="true">http://www.kimchy.org/compass-202-released/</guid>
      <dc:creator>Shay Banon</dc:creator>
    </item>
    <item>
      <title>How Buildings Learn</title>
      <link>http://www.groovygrails.com/blog/michael_nygard/2008/08/how_buildings_learn.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>&lt;p&gt;Stewart Brand's famous book &lt;a href="http://www.amazon.com/gp/product/0140139966?ie=UTF8&amp;tag=michaelnygard-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0140139966"&gt;How Buildings Learn&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=michaelnygard-20&amp;l=as2&amp;o=1&amp;a=0140139966" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt; has been on my reading queue for a while, possibly a few years. Now that I've begun reading it, I wish I had gotten it sooner. Listen to this:&lt;/p&gt;

&lt;blockquote&gt;The finished-looking model and visually obsessive renderings dominate the let's-do-it meeting, so that shallow guesses are frozen as deep decisions. All the design intelligence gets forced to the earliest part of the building process, when everyone knows the least about what is really needed.&lt;/blockquote&gt;

&lt;p&gt;Wow. It's hard to tell what industry he's talking about there. It could easily apply to software development. No wonder Brand is so well-regarded in the Agile community!&lt;/p&gt;

&lt;p&gt;Another wonderful parallel is between what Brand calls &amp;quot;Low Road&amp;quot; and &amp;quot;High Road&amp;quot; buildings. A Low Road building is one that is flexible, cheap, and easy to modify. It's hackable. Lofts, garages, old factory floors, warehouses, and so on. Each new owner can gut and modify it without qualms. A building where you can drill holes through the walls, run your own cabling, and rip out every interior wall is a Low Road building.&lt;/p&gt;

&lt;p&gt;High Road buildings evolve gradually over time, through persistent care and love. There doesn't necessarily have to be a consistent--or even coherent--vision, but each own does need to feel a strong sense of preservation. High Road buildings become monuments, but they aren't &lt;i&gt;made&lt;/i&gt; that way. They just evolve in that direction as each generation adds their own character.&lt;/p&gt;

&lt;p&gt;Then there are the buildings that aren't High or Low Road. Too static to be Low Road, but not valued enough to be High Road. Resistant to change, bureaucratic in management. Diffuse responsibility produces static (i.e., dead) buildings. Deliberately setting out to design a work of art, paradoxically, prevents you from creating a living, livable building.&lt;/p&gt;

&lt;p&gt;Again, I see some clear parallels to software architecture here. On the one hand, we've got Low Road architecture. Easy to glue together, easy to rip apart. Nobody gets bent out of shape if you blow up a hodge-podge of shoestring batch jobs and quick-and-dirty web apps. CGI scripts written in perl are classic Low Road architecture. It doesn't mean they're bad, but they're probably not going to go a long time without being changed in some massive ways.&lt;/p&gt;

&lt;p&gt;High Road architecture would express a conservativism that we don't often see. High Road is &lt;i&gt;not&lt;/i&gt; &amp;quot;big&amp;quot; architecture. Rather, High Road means cohesive systems lovingly tended. Emacs strikes me as a good example of High Road architecture. Yes, it's accumulated a lot of bits and oddments over the years, but it's quite conservative in its architecture.&lt;/p&gt;

&lt;p&gt;Enterprise SOA projects, to me, seem like dead buildings. They're overspecified and too focused on the moment of rollout. They're the grand facades with leaky roofs. They're the corporate office buildings that get gerrymandered into paralysis. They preach change, but produce stasis.&lt;/p&gt;</description>
      <pubDate>Tue, 19 Aug 2008 13:00:02 CDT</pubDate>
      <guid isPermaLink="true">http://www.michaelnygard.com/blog/2008/08/how_buildings_learn.html</guid>
      <dc:creator>Michael Nygard</dc:creator>
    </item>
    <item>
      <title>Does Your Team Have STDs?</title>
      <link>http://www.groovygrails.com/blog/jared_richardson/2008/08/does_your_team_have_stds_.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>Last week I was talking with a friend about a common ailment on development teams today. And it seems to be getting worse. 
&lt;br/&gt;&lt;br/&gt;
Perhaps you've seen it already in your shop. Once one person catches an STD, it seems to spread quickly.
&lt;br/&gt;&lt;br/&gt;
STD, of course, stands for Shiny Things Development. 
&lt;br/&gt;&lt;br/&gt;
Oh cool! Check that out... it's new and cool. Let's include it in the product! Why? Umm... it solves some problem. And didn't I just say it's shiny and new?
&lt;br/&gt;&lt;br/&gt;
How many shops have you met that have insane development infrastructures "just in case" things get crazy? Anytime the shop has a list of tools and libraries where every single one requires a specific version for anything to work, someone there has STD.
&lt;br/&gt;&lt;br/&gt;
What's the problem with STD? It generally indicates a lack of discretion and promiscuous use of technology. Rather than saving yourself for something that actually works, you're chasing down every new product and technology. Sure, it might be fun to try out new stuff</description>
      <pubDate>Tue, 19 Aug 2008 11:00:04 CDT</pubDate>
      <guid isPermaLink="true">http://agileartisans.com/main/blog/125</guid>
      <dc:creator>Jared Richardson</dc:creator>
    </item>
    <item>
      <title>Need Help with BackUpWordPress</title>
      <link>http://www.groovygrails.com/blog/johanna_rothman/2008/08/need_help_with_backupwordpress.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>&lt;p&gt;I&amp;#8217;ve been using BackUpWordPress to backup my blogs. I successfully upgraded &lt;a href="http://www.jrothman.com/blog/htp" target="_blank"&gt;Hiring Technical People&lt;/a&gt; to a newer version of WP and of BackUpWordPress. I upgraded this blog, Managing Product Development, to the newer version of WP, but now my newer version of BackUpWordPress is not working. I&amp;#8217;m pretty sure it&amp;#8217;s all about file permissions.&lt;/p&gt;
&lt;p&gt;If you have experience with this and insight, please email me, jr at jrothman dot com. I can&amp;#8217;t figure out what I&amp;#8217;m doing wrong and want to keep backing up! Thanks.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/ManagingProductDevelopment?a=86EkxK"&gt;&lt;img src="http://feeds.feedburner.com/~f/ManagingProductDevelopment?i=86EkxK" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ManagingProductDevelopment?a=S2BulK"&gt;&lt;img src="http://feeds.feedburner.com/~f/ManagingProductDevelopment?i=S2BulK" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ManagingProductDevelopment?a=Vb7mnk"&gt;&lt;img src="http://feeds.feedburner.com/~f/ManagingProductDevelopment?i=Vb7mnk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ManagingProductDevelopment?a=ctOSYk"&gt;&lt;img src="http://feeds.feedburner.com/~f/ManagingProductDevelopment?i=ctOSYk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ManagingProductDevelopment?a=XgP9lK"&gt;&lt;img src="http://feeds.feedburner.com/~f/ManagingProductDevelopment?i=XgP9lK" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/ManagingProductDevelopment?a=LkYCuK"&gt;&lt;img src="http://feeds.feedburner.com/~f/ManagingProductDevelopment?i=LkYCuK" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ManagingProductDevelopment/~4/368422634" height="1" width="1"/&gt;</description>
      <pubDate>Tue, 19 Aug 2008 08:00:02 CDT</pubDate>
      <guid isPermaLink="true">http://jrothman.com/blog/mpd/?p=8475</guid>
      <dc:creator>Johanna Rothman</dc:creator>
    </item>
    <item>
      <title>Name Soup</title>
      <link>http://www.groovygrails.com/blog/alex_russell/2008/08/name_soup.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>&lt;p&gt;There still seems to be &lt;a href="http://tech.slashdot.org/article.pl?sid=08/08/16/1552227&amp;#038;from=rss"&gt;an amazing amount of FUD&lt;/a&gt; going around regarding the Harmony announcement. There is clearly a very different perspective from those who have been sitting inside the WG for the past year (as &lt;a href="http://www.json.com/"&gt;Kris Zyp&lt;/a&gt; and I have been lucky to). Inside the WG, the change seems a welcome way to break a logjam of reasonably held opinions of people who are all acting in good faith. From the outside, it all looks like confusion and game-playing.&lt;/p&gt;
&lt;p&gt;One of the things, though, that keeps getting me frustrated as I read the &amp;#8220;coverage&amp;#8221; is that the names people use are confused. Probably because the names are &lt;em&gt;confusing&lt;/em&gt;. Here&amp;#8217;s a quick glossary:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;ECMAScript 3&lt;/dt&gt;
&lt;dd&gt;Aka: JavaScript, ES3, ECMAScript 262-3, and JScript.&lt;/p&gt;
&lt;p&gt;The current JavaScript that every browser implements (more or less). This is the current ratified standard and represents the 3rd edition of the ECMAScript spec. It is very old. Nothing else in this list is (yet) a ratified standard of any sort.&lt;/dd&gt;
&lt;dt&gt;ECMAScript 4&lt;/dt&gt;
&lt;dd&gt;Aka: ES4, &amp;#8220;JavaScript 2&amp;#8243;. &lt;/p&gt;
&lt;p&gt;A new language which was to be mostly backwards compatible but add optional (gradual) typing and class-based inheritance. Based loosely on Adobe&amp;#8217;s ActionScript 3. This is the language effort which died as a result of Harmony.&lt;/dd&gt;
&lt;dt&gt;ECMAScript 3.1&lt;/dt&gt;
&lt;dd&gt;Aka: ES3.1. A set of small additions to ES3.&lt;/p&gt;
&lt;p&gt;Planning for this edition was started at Microsoft and Yahoo&amp;#8217;s behest late last year, causing the split in the working group which has been healed by the Harmony announcement.&lt;/dd&gt;
&lt;dt&gt;ActionScript 3&lt;/dt&gt;
&lt;dd&gt;Aka: AS3&lt;/p&gt;
&lt;p&gt;Adobe&amp;#8217;s current JavaScript-like language, only with many features lifted from languages like Java which also enforce types and class-based semantics. This was the starting point for much of the work which became known as ES4.&lt;/dd&gt;
&lt;dt&gt;Tamarin&lt;/dt&gt;
&lt;dd&gt;A JIT-ing byte-code virtual machine (VM) which is at the core of the Flash Player and was donated by Adobe to the Mozilla Foundation. This is the VM that runs ActionScript 3 code today but will likely run &amp;#8220;real&amp;#8221; JavaScript for Mozilla in the future. It is not a full implementation of ES3 or ES4, but instead implements its own byte-code and needs to be wedded to a &amp;#8220;front end&amp;#8221; (like the ActionScript 3&lt;br /&gt;
compiler from Adobe) in order to be usable by programmers.&lt;/dd&gt;
&lt;dt&gt;Tamarin-tracing&lt;/dt&gt;
&lt;dd&gt;A VM which implements the same byte-code language as Tamarin (known as &amp;#8220;ABC&amp;#8221;) but which is designed for use in mobile devices and other scenarios where code size and VM footprint are important. It implements trace-tree JIT-ing as a way to speed up hot-spots. Also donated to Mozilla by Adobe.&lt;/dd&gt;
&lt;dt&gt;TC39&lt;/dt&gt;
&lt;dd&gt;The name of the &lt;a href="http://www.ecma-international.org/memento/TC39.htm"&gt;ECMA technical committee&lt;/a&gt; which is chartered to evolve the JavaScript language.&lt;/dd&gt;
&lt;dt&gt;Harmony&lt;/dt&gt;
&lt;dd&gt;A new code-name for a language which is to come after ES3.1. It will feature many of the things ES4 was trying to accomplish, but may attempt them from different directions and will&lt;br /&gt;
focus much more on incremental, step-wise evolution of the language.
&lt;/dd&gt;
&lt;dt&gt;JavaScript 2&lt;/dt&gt;
&lt;dd&gt;A now-defunct name. This name was originally given to Waldemar Horwat&amp;#8217;s first proposal at a large-scale evolution of the JavaScript language in 1999. That effort did not succeed (although Microsoft implemented some of it in JScript.NET) and subsequent work via the current TC39 charter to build ES4 has sometimes been given the name &amp;#8220;JavaScript 2&amp;#8243;, but it never really stuck. Not a name that describes any ratified standard or current proposal.
&lt;/dd&gt;
&lt;dt&gt;ECMAScript&lt;/dt&gt;
&lt;dt&gt;
&lt;dd&gt;The formalized name of the JavaScript language. Since Sun Microsystems owns the name JavaScript and has no idea what to do with the trademark (but has been benevolent thus far), the ECMA committee which standardized the language was forced to adopt a different name.&lt;/dd&gt;
&lt;/dt&gt;
&lt;/dl&gt;</description>
      <pubDate>Mon, 18 Aug 2008 16:00:01 CDT</pubDate>
      <guid isPermaLink="true">http://alex.dojotoolkit.org/?p=736</guid>
      <dc:creator>Alex Russell</dc:creator>
    </item>
    <item>
      <title>Cloud-Oriented Architecture (COA)</title>
      <link>http://www.groovygrails.com/blog/scott_leberknight/2008/08/cloud_oriented_architecture_coa_.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>&lt;p&gt;With all the hype this year about cloud computing and things like Amazon EC2/S3 as well as Google App Engine and Bigtable, you can feel it coming. Soon vendors will be peddling &lt;strong&gt;COA&lt;/strong&gt; (Cloud-Oriented Architecture) solutions, probably combining them with their SOA solution and somehow probably getting their ESB solution into the mix as well. This past weekend at the Enterprise Architecture BOF at the &lt;a href="http://www.nofluffjuststuff.com/conference/cincinnati/2008/08/index.html"&gt;Southern Ohio Software Symposium&lt;/a&gt;, we had a discussion about cloud computing among other things. &lt;a href="http://blogs.tedneward.com/"&gt;Ted Neward&lt;/a&gt; even coined the term "Enterprise Service Cloud" and I came up with "Cloud Service Bus," surely the next Big Thing. Any vulture (I mean, venture) capitalists out there want to invest in my new Cloud Service Bus company? I have a pretty brochure ready to go!&lt;/p&gt;

&lt;p&gt;The big difference I see with regard to cloud computing is the fact that, unlike your typical ESB/SOA peddling vendors, companies like Amazon and Google &lt;emphasis&gt;already have cloud or cloud-like solutions in place&lt;/emphasis&gt; a la Amazon &lt;a href="http://aws.amazon.com/ec2"&gt;EC2&lt;/a&gt;/&lt;a href="http://aws.amazon.com/s3"&gt;S3&lt;/a&gt; and &lt;a href="http://www.allthingsdistributed.com/2007/10/amazons_dynamo.html"Dynamo&lt;/a&gt;, and &lt;a href="http://code.google.com/appengine/"&gt;Google App Engine&lt;/a&gt; and &lt;a href="http://labs.google.com/papers/bigtable.html"&gt;Bigtable&lt;/a&gt;. Now all of those things just mentioned are not "the cloud" (whatever "the cloud" actually is defined to be), but it doesn't matter because the point is these companies have designed, implemented, and most importantly, run their critical business operations on these platforms. That in and of itself is more important than all the vaporware and marketing hype any other vendor comes up with. Rather than having to get customers to believe that a solution works via marketing and then force it down their IT staff's throats, Google and Amazon are basically saying "Hey why not use stuff that we use and have proven can scale up to handle huge loads and huge amounts of data?"&lt;/p&gt;

&lt;p&gt;To me as a developer this is a much more appealing approach for several reasons. First, it means there won't be (or shouldn't need to be) any "golf-course deals" where the vendor sales guys and customer CIOs/CTOs/CEOs meet up and decide on the technology stack independent of any real technical analysis, investigation, or input of the people who will be charged with implementing the vendor stack (and they better do it well else it's their job on the line to boot).&lt;/p&gt;

&lt;p&gt;Second, I can base my decision to use a Google or Amazon service based on  their actual track record in delivering these services and eating their own dog food, since they are trying to monetize their existing investment in proven highly distributed and scalable infrastructures. Yes, there have been Amazon outages this year and whenever it happens it is big news because it is right there out in the public, as opposed to a company whose IT operations are totally in-house and which isn't going to publicize their downtime statistics. I'd wager on Amazon and Google's availability over probably most other companies. Of course I have no way to prove that last statement, but the mere fact that I can get objective statistics on their services helps in my decision making process and planning.&lt;/p&gt;

&lt;p&gt;Last, I can decide how much or how little to outsource to the Amazon or Google infrastructure; for example some organizations might choose to keep their most sensitive data (e.g. customer information, credit card numbers, etc.) in-house but outsource everything else to, say, an Amazon EC2/S3 infrastructure. There is still some level of vendor lock-in here, but there is with anything else short of you implementing your own solution from scratch. And if, by leveraging proven solutions by companies like Amazon and Google, you are able to deliver real value to your customers faster and are able to scale up, out, and beyond without needing to build that infrastructure yourself, then I'd say that could potentially equate to a big win.&lt;/p&gt;

&lt;p&gt;So when that vendor comes calling with their shiny new COA solution, be very afraid, and make sure you know your options and present them objectively. We as an industry have more buzzwords and hype (at least from my perspective) than almost any other, and this causes more money than I can possibly imagine to be wasted every year on solutions that don't (and never will) work as advertised. Developers often have a feeling that the VDD (vendor-driven development) solutions just won't work, but cannot convince their managers or their managers' managers of this fact, which is why communications skills are critical in today's world. I don't know about you, but I don't want to be the person who becomes responsible for implementing a solution I don't believe in.&lt;/p&gt;

&lt;p&gt;"The Cloud" and cloud computing are definitely here to stay forever, and as Amazon and Google have proven, can add huge amounts of value to businesses. I am sure there will be other companies perhaps trying to implement similar strategies and monetizing their investment in their own infrastructure, and that will be mostly a good thing to have different options and competition to further push the Cloud Service Providers (CSPs) to continually improve their offerings. Get ready, because our toolboxes have just become a &lt;strong&gt;lot bigger&lt;/strong&gt;.&lt;/p&gt;</description>
      <pubDate>Mon, 18 Aug 2008 13:00:02 CDT</pubDate>
      <guid isPermaLink="true">http://www.sleberknight.com/blog/sleberkn/entry/cloud_oriented_architecture_coa</guid>
      <dc:creator>Scott Leberknight</dc:creator>
    </item>
    <item>
      <title>jSilhouette update</title>
      <link>http://www.groovygrails.com/blog/andres_almiray/2008/08/jsilhouette_update.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>A couple of days ago there was an announcement on this blog about &lt;a href="http://code.google.com/p/jsilhouette/"&gt;jSilhouette&lt;/a&gt;'s &lt;a href="http://www.jroller.com/aalmiray/entry/announcing_jsilhouette"&gt;0.1 release&lt;/a&gt;, followed by a &lt;a href="http://www.jroller.com/aalmiray/entry/jsilhuette_demo_screenshots_and_code"&gt;comparison&lt;/a&gt; between the geom, scene and jfx demos (regular Java, Project SceneGraph and JavaFx Script each).&lt;br/&gt;&lt;br/&gt;Things have changed a bit. Jacek Furmankiewicz brought to my attention that Project SceneGraph is licensed under GPLv2 (no classpath extension) which means both jsilhouette-scene and jsilhouette-jfx &lt;b&gt;must&lt;/b&gt; use the same licensing scheme. But jsilhouette-geom does not, in fact it has been re-licensed to ASL 2.0, this means that starting with the next release commercial use of jsilhouette-geom is no longer a problem. The commercial usefulness of the remaining modules lies in Sun's will to re-license Project SceneGraph to GPLv2 with classpath extension.&lt;br/&gt;&lt;br/&gt;Some other updates&lt;ul&gt;
&lt;li&gt;Donut shape has been added to all modules. Donuts may be circular or polygonal.&lt;/li&gt;
&lt;li&gt;Default values have been added to some attributes in the jfx module, alleviating the pain of setting each attribute.&lt;/li&gt;
&lt;li&gt;Groovy demo (GraphicsBuilder based) available!&lt;/li&gt;
&lt;/ul&gt;Here is an screenshot on the latest demo app&lt;br/&gt;&lt;br/&gt;&lt;center&gt;&lt;img src="http://www.jroller.com/aalmiray/resource/jsilhouette-demo-groovy.png"/&gt;&lt;/center&gt;&lt;br/&gt;&lt;br/&gt;Nice Nimbus look &amp;amp;feel, you may be thinking that this is the new version of the jfx demo, but it is not! this is the Groovy version (&lt;a href="http://code.google.com/p/jsilhouette/source/browse/trunk/jsilhouette-groovy/src/demo/groovy/org/kordamp/jsilhouette/ShapesDemoGroovy.groovy"&gt;ShapesDemoGroovy.groovy&lt;/a&gt;) &lt;img src="http://www.jroller.com/images/smileys/wink.gif" class="smiley" alt=";-)" title=";-)" /&gt; , the green color is darker in jfx, remember? let's revisit the stats, shall we? &lt;br/&gt;&lt;br/&gt;&lt;center&gt;
&lt;table border="1"&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&amp;nbsp;&lt;/th&gt;
&lt;th&gt;geom&lt;/th&gt;
&lt;th&gt;scene&lt;/th&gt;
&lt;th&gt;jfx&lt;/th&gt;
&lt;th&gt;groovy&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;&lt;b&gt;LoC&lt;/b&gt;&lt;/td&gt;
&lt;td valign="top"&gt;369&lt;/td&gt;
&lt;td valign="top"&gt;505&lt;/td&gt;
&lt;td valign="top"&gt;619&lt;/td&gt;
&lt;td valign="top"&gt;369&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;&lt;b&gt;Tokens&lt;/b&gt;&lt;/td&gt;
&lt;td valign="top"&gt;1486&lt;/td&gt;
&lt;td valign="top"&gt;1855&lt;/td&gt;
&lt;td valign="top"&gt;2644&lt;/td&gt;
&lt;td valign="top"&gt;2194&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;&lt;b&gt;Source file size (bytes)&lt;/b&gt;&lt;/td&gt;
&lt;td valign="top"&gt;16412&lt;/td&gt;
&lt;td valign="top"&gt;21000&lt;/td&gt;
&lt;td valign="top"&gt;20626&lt;/td&gt;
&lt;td valign="top"&gt;15311&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td valign="top"&gt;&lt;b&gt;Compiled code size (bytes)&lt;/b&gt;&lt;/td&gt;
&lt;td valign="top"&gt;104K&lt;/td&gt;
&lt;td valign="top"&gt;60K&lt;/td&gt;
&lt;td valign="top"&gt;76K&lt;/td&gt;
&lt;td valign="top"&gt;92K&lt;/td&gt;
&lt;/tr&gt;

&lt;/tbody&gt;
&lt;/table&gt;&lt;/center&gt;&lt;br/&gt;The Groovy version beats the JavaFx Script version in almost all categories (the source file is even shorter than the Java2D version) but these numbers do not reflect how small the code can be in each version. For example I discovered that the jfx version has some commas (,) between attribute declaration (which bump the char and file size), I was surprisewd to find out JavaFx Script was happy with them as not even a slight warning is given by the compiler, nice!; the Groovy version harnesses the power of native syntax for Lists and Maps to reduce variable declaration; defaults values are not really used that much in all versions.&lt;br/&gt;&lt;br/&gt;I also mentioned previously that making the second and third demo was quicker once the first one was done, in this case it was no different. The jfx version was copied almost verbatim, added some Groovy sugar here and there (even had to add a MetaClass hack due to how SwingBuilder handles look&amp;amp;feel in the 1.5.6 version (the new one is slicker &lt;img src="http://www.jroller.com/images/smileys/grin.gif" class="smiley" alt=":-D" title=":-D" /&gt; thank &lt;a href="http://twitter.com/shemnon"&gt;@shemnon&lt;/a&gt; for that)). Quick comparison between how the jfx and groovy versions initialize the frame, first the jfx one&lt;br/&gt;&lt;textarea name="srccode" class="jfx:nocontrols:nogutter" cols="80" rows="26"&gt;SwingFrame {
   title: "jSilhouette Shapes (JavaFX)"
   visible: true
   closeAction: function() { System.exit(0); }
   width: 500
   height: 400
   content: BorderPanel {
      center: canvas /*an instance of Canvas*/
      left: GridPanel {
         columns: 1
         rows: 10
         content: [
            SwingButton { text: "Arrow"    action: drawArrows },
            SwingButton { text: "Balloon"  action: drawBalloons },
            SwingButton { text: "Cross"    action: drawCrosses },
            SwingButton { text: "Donut"    action: drawDonuts },
            SwingButton { text: "MultiRoundRectangle" action: drawMultiRoundRectangles },
            SwingButton { text: "Rays"     action: drawRays },
            SwingButton { text: "RegularPolygon" action: drawRegularPolygons },
            SwingButton { text: "RoundPin" action: drawRoundPins },
            SwingButton { text: "Star2"    action: drawStars },
            SwingButton { text: "Triangle" action: drawTriangles }
         ]
      }
   }
}&lt;/textarea&gt;&lt;br/&gt;Where each &lt;code&gt;draw*&lt;/code&gt; function is of the form&lt;br/&gt;&lt;textarea name="srccode" class="jfx:nocontrols:nogutter" cols="80" rows="11"&gt;var canvas: Canvas = Canvas { }

var drawArrows = function():Void {
   canvas.content = [
      Arrow {
         x: 20 y: 20 width: 100 height: 60 rise: 0.5 depth: 0.5 
         fill: Color.RED stroke: Color.BLACK
      },
      ...
   ]
}&lt;/textarea&gt;&lt;br/&gt;Here I'd like to take the opportunity to mention that the function signature must have &lt;code&gt;Void&lt;/code&gt; as its return type otherwise a compilation error will be thrown. If the return type is not specified then it will be the same type of the last evaluated expression, in this case &lt;code&gt;Node[]&lt;/code&gt;, SwingButton expects its &lt;code&gt;action&lt;/code&gt; function to return &lt;code&gt;Void&lt;/code&gt;. I'm sure a tool (like NetBeans' jfx plugin) would have drawn a red underline/popped an error/whatever under the offending code before attempting a full compile on the code by myself, but I went with the "manual" way: Vim + command line compiler, so there, had to be more careful &lt;img src="http://www.jroller.com/images/smileys/tongue.gif" class="smiley" alt=":-P" title=":-P" /&gt;&lt;br/&gt;&lt;br/&gt;Here is the Groovy version&lt;br/&gt;&lt;textarea name="srccode" class="groovy:nocontrols:nogutter" cols="80" rows="28"&gt;/* Groovy 1.5.6- hack */
SwingBuilder.metaClass.lookAndFeel = { List lafs -&gt;
   for( laf in lafs ) {
      try{ delegate.lookAndFeel(laf); break }
      catch( ex ) {/* ignore */}
   }
}

SwingBuilder.build {
  lookAndFeel( ['nimbus', 'mac', 'gtk', 'metal'] )
  frame( title: 'jSilhouette Shapes (Groovy)', size: [500,400],
         defaultCloseOperation: JFrame.EXIT_ON_CLOSE, show: true,
         locationRelativeTo: null ) {
    borderLayout()
    panel( new GraphicsPanel(), id: 'canvas', constraints: BL.CENTER )
    panel( constraints: BL.WEST) {
      gridLayout( columns: 1, rows: shapes.size() )
      shapes.each { shape, graphicsOperation -&gt;
        button( shape, actionPerformed: { evt -&gt;
          def group = gb.group( borderColor: 'black' )
          group &lt;&lt; gb.antialias(true)           group &lt;&lt; graphicsOperation           canvas.graphicsOperation = group         })       }     }   } }&lt;/textarea&gt;&lt;br/&gt;Where &lt;code&gt;shapes&lt;/code&gt; is a Map initialized like&lt;br/&gt;&lt;textarea name="srccode" class="groovy:nocontrols:nogutter" cols="80" rows="9"&gt;def gb = new GraphicsBuilder()

def shapes = [
   'Arrow': gb.group {
      arrow( x: 20, y: 20, width: 100, height: 60, rise: 0.5, depth: 0.5,
             fill: 'red' )
    },
    ...
]&lt;/textarea&gt;&lt;br/&gt;The Groovy version requires some 'blumbing'&lt;ul&gt;
&lt;li&gt;Fix &lt;code&gt;SwingBuilder.lookAndFeel&lt;/code&gt; to accept a List of L&amp;amp;F identifiers (available in Groovy 1.6.x).&lt;/li&gt;
&lt;li&gt;Set the preferred L&amp;amp;F.&lt;/li&gt;
&lt;li&gt;Tell the frame where it should be located by default (locationRelativeTo: null)&lt;/li&gt;
&lt;/ul&gt;The native syntax for Lists and Maps comes in our aid here. Iterating each entry (String,GraphicsOperation) it is a matter of hooking up the proper values on the button's text and action. Notice that each time a button is clicked a new GraphicsOperation is created (a group) that has a 'global' property applied to all its children (borderColor: 'black') and antialias is turned on. GraphicsPanel is smart enough to know when it should repaint itself (similar to JSGPanel and Canvas). Of course some would say you may iterate over a sequence in the jfx version in order to build the buttons in a loop, sure you can. You could also create a java.util.Map that holds each label and related function, but the code is not as concise as the Groovy one. Assuming hypothetical classes javafx.util.LinkedHashMap and javafx.util.MapEntry&lt;br/&gt;&lt;textarea name="srccode" class="jfx:nocontrols:nogutter" cols="80" rows="17"&gt;var shapes = LinkedHashMap {
   content: [
      MapEntry { key: 'Arrow'
         value : [
            Arrow { ... }, ...
         ]
      },
      ...
   ]
}
...
shapes.eachEntry ( function(key:Object,value:Object):Void {
   var label = key as String;
   var actionFunc = value as Function; // (???)
   var button = SwingButton { text: label, action: actionFunc }
   // insert button in its proper place
})&lt;/textarea&gt;Yup, hypothetical is more like it (my code that is, still have to learn more about JavaFx Script) but you get the idea. Back to jSilhouette, I'd like to have proper javadocs/javafxdocs in place before releasing the next version, so it will take a couple of days more.&lt;br/&gt;&lt;br/&gt;Feedback is always appreciated.</description>
      <pubDate>Mon, 18 Aug 2008 11:00:02 CDT</pubDate>
      <guid isPermaLink="true">http://www.jroller.com/aalmiray/entry/jsilhouette_update</guid>
      <dc:creator>Andres Almiray</dc:creator>
    </item>
    <item>
      <title>Testing Anti-Patterns: Invisible Code</title>
      <link>http://www.groovygrails.com/blog/jason_rudolph/2008/08/testing_anti_patterns_invisible_code.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>&lt;p&gt;As we&amp;#8217;ve seen over the last several weeks, it&amp;#8217;s remarkably easy for code to earn the badge of 100% &lt;a href="http://jasonrudolph.com/blog/2008/06/10/a-brief-discussion-of-code-coverage-types/" title="jasonrudolph.com/blog - A Brief Discussion of Code Coverage Types"&gt;test coverage&lt;/a&gt; &lt;em&gt;without&lt;/em&gt; necessarily having a strong test suite.  In &lt;a href="http://jasonrudolph.com/blog/tag/testing-anti-patterns/" title="jasonrudolph.com/blog - Testing Anti-Patterns"&gt;each of those examples&lt;/a&gt;, the coverage analysis tool performed its task flawlessly: it reported exactly which portions of our code were executed as a result of running the tests.  The all-green coverage report showed us that the tests indeed touched all of our code, but it was up to us to acknowledge that simply touching a line of code doesn&amp;#8217;t mean that you&amp;#8217;ve exercised and verified that line of code in a meaningful way.  Some folks interpret this acknowledgement to mean that coverage analysis is meaningless, but that unfortunate conclusion overlooks the real benefit of a coverage report: it&amp;#8217;s not about getting to 100% test coverage and assuming victory, it&amp;#8217;s about highlighting any areas of our codebase that we&amp;#8217;ve forgotten to test entirely.&lt;/p&gt;

&lt;p&gt;As with any tool, to make effective use of coverage analysis, we need to understand its purpose, its capabilities, and its limitations.  In all of the previous examples, we looked at code that was already in the coverage report.  In other words, the coverage tool knew about this code and was able to watch the code and assess its coverage upon completion of the test suite.  But if we&amp;#8217;re using the coverage report to help us find untested code, how do we deal with code that the coverage tool might not be aware of in the first place?&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s start with a sample Rails app that represents the beginnings of an online store.  The project currently contains the following files (as well as some others that I&amp;#8217;ve omitted for the sake of brevity).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[store]$ tree
...
|-- app
|   |-- controllers
|   |   |-- application.rb
|   |   `-- products_controller.rb
|   |-- helpers
|   |   |-- application_helper.rb
|   |   `-- products_helper.rb
|   |-- models
|   |   `-- product.rb
|   `-- views
|       |-- layouts
|       |   `-- products.html.erb
|       `-- products
|           |-- edit.html.erb
|           |-- index.html.erb
|           |-- new.html.erb
|           `-- show.html.erb
|-- config
|   |-- boot.rb
|   |-- database.yml
|   |-- environment.rb
|   |-- environments
|   |   ...
|   |-- initializers
|   |   |-- inflections.rb
|   |   |-- mime_types.rb
|   |   `-- new_rails_defaults.rb
|   `-- routes.rb
|-- db
|   |-- migrate
|   |   `-- 20080810220638_create_products.rb
|   `-- schema.rb
...
|-- lib
|   |-- product_ftp_importer.rb
|   `-- tasks
|   |   |-- data_load.rake
...
|-- test
|   |-- fixtures
|   |   `-- products.yml
|   |-- functional
|   |   `-- products_controller_test.rb
|   |-- integration
|   |-- test_helper.rb
|   `-- unit
|       `-- product_test.rb
...

37 directories, 63 files
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;After installing the &lt;a href="http://agilewebdevelopment.com/plugins/rails_rcov" title="Plugins - Rails rcov - Agile Web Development"&gt;rails_rcov plugin&lt;/a&gt;, we can easily produce a coverage report to see where we currently stand.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://jasonrudolph.com/blog/wp-content/uploads/20080819_invisible_code_coverage_report_1.png"&gt;&lt;img src="http://jasonrudolph.com/blog/wp-content/uploads/20080819_invisible_code_coverage_report_1_thumb.png" alt="100% Test Coverage" title="100% Test Coverage - The Whole Story?" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;According to the coverage report, we&amp;#8217;re not aware of any code that isn&amp;#8217;t touched by at least one test.  But is that really the whole story?  The number of test-related files sure accounts for a small proportion of the overall app.  We can see that we have &lt;code&gt;test/unit/product_test.rb&lt;/code&gt; and &lt;code&gt;test/functional/products_controller_test.rb&lt;/code&gt;, but do those two files really encompass all the developer testing needed for this application?&lt;/p&gt;

&lt;h2&gt;Out of Sight, Out of Mind?&lt;/h2&gt;

&lt;p&gt;What about that mysterious file hanging out in the &lt;code&gt;lib&lt;/code&gt; directory?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[store]$ tree
...
|-- lib
|   |-- product_ftp_importer.rb
...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Just judging by the name of the file, that sure &lt;em&gt;sounds&lt;/em&gt; like functionality that deserves testing, but for some reason it&amp;#8217;s not listed in the coverage report.  And if we take another look at the test files listed above, there are no test files that obviously correlate to &lt;code&gt;product_ftp_importer.rb&lt;/code&gt;.  So, how is it that we have 100% coverage?&lt;/p&gt;

&lt;p&gt;In order for code to show up in a coverage report, we need to instruct the coverage tool to assess that file.  The approach for doing so tends to vary from tool to tool.  With &lt;a href="http://eigenclass.org/hiki.rb?rcov" title="eigenclass - rcov: code coverage for Ruby"&gt;rcov&lt;/a&gt;, we first have to tell it which files constitute our test suite (i.e., the files we want rcov to run).  But that alone is not sufficient; we also have to ensure that application files (i.e., the files whose test coverage we want to measure) get &lt;em&gt;loaded&lt;/em&gt; as part of the test suite.  Adding this &lt;code&gt;require&lt;/code&gt; statement anywhere in our test suite is enough to shed some light on the elusive code in &lt;code&gt;product_ftp_importer.rb&lt;/code&gt;.&lt;/p&gt;

&lt;div class="dean_ch" style="white-space: wrap;"&gt;&lt;ol&gt;&lt;li class="li1"&gt;&lt;div class="de1"&gt;&lt;span class="kw3"&gt;require&lt;/span&gt; &lt;span class="kw4"&gt;File&lt;/span&gt;.&lt;span class="me1"&gt;expand_path&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw4"&gt;File&lt;/span&gt;.&lt;span class="me1"&gt;dirname&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="kw2"&gt;__FILE__&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; + &lt;span class="st0"&gt;&amp;quot;/../lib/product_ftp_importer&amp;quot;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;

&lt;p&gt;&lt;br/&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://jasonrudolph.com/blog/wp-content/uploads/20080819_invisible_code_coverage_report_2.png"&gt;&lt;img src="http://jasonrudolph.com/blog/wp-content/uploads/20080819_invisible_code_coverage_report_2_thumb.png" alt="71.7% Test Coverage" title="71.7% Test Coverage - The Whole Story" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s hard to feel good about 45 lines of untested FTP-processing voodoo, so how can we unearth this &lt;strong&gt;invisible code&lt;/strong&gt; as soon as it tries to sneak its way into our app?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure that your coverage task knows where to find your tests, always place new tests where the coverage task can find them, and use a consistent naming scheme so that a simple file-matching pattern can distinguish test files from non-test files.&lt;/li&gt;
&lt;li&gt;If you&amp;#8217;re using rcov, add a quick script that will crawl your project tree and &lt;code&gt;require&lt;/code&gt; all application files.  Adding individual &lt;code&gt;require&lt;/code&gt; statements one-by-one is not a reasonable solution.  If someone&amp;#8217;s not going to write the test in the first place, they&amp;#8217;re sure as heck not gonna take the time to tell the coverage report about that misdeed.  So, walk the tree and require any Ruby file that you encounter in places where application code is likely to turn up.  At the very least, in a Rails app you should include all subdirectories under &lt;code&gt;app&lt;/code&gt; (being aggressive enough to catch any &lt;em&gt;new&lt;/em&gt; directories that might get added there) and the &lt;code&gt;lib&lt;/code&gt; directory.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;(Not So) Scenic View Ahead&lt;/h2&gt;

&lt;p&gt;View templates have long been a favorite dumping ground for misplaced application logic.  This problem can often go undetected, because view templates fly under the radar of the coverage report.  Most developers know they should minimize the application logic included in the view, but when a deadline&amp;#8217;s looming, the lure of throwing some code in the view &amp;#8220;just this once&amp;#8221; is often hard to resist.  For example, what&amp;#8217;s so wrong with having the view decide whether to display a particular product in the list?&lt;/p&gt;

&lt;div class="dean_ch" style="white-space: wrap;"&gt;&lt;ol&gt;&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;lt;% &lt;span class="kw1"&gt;for&lt;/span&gt; product &lt;span class="kw1"&gt;in&lt;/span&gt; &lt;span class="re1"&gt;@products&lt;/span&gt; %&amp;gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;lt;% &lt;span class="kw1"&gt;if&lt;/span&gt; product.&lt;span class="me1"&gt;quantity_in_stock&lt;/span&gt; &amp;gt; &lt;span class="nu0"&gt;0&lt;/span&gt; &amp;amp;&amp;amp; product.&lt;span class="me1"&gt;quantity_in_stock&lt;/span&gt; &amp;gt; product.&lt;span class="me1"&gt;pending_backorder_count&lt;/span&gt; %&amp;gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;!&amp;#8211; display purchasable product here &amp;#8211;&amp;gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;!&amp;#8211; &amp;#8230; &amp;#8211;&amp;gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;lt;% &lt;span class="kw1"&gt;end&lt;/span&gt; %&amp;gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;lt;% &lt;span class="kw1"&gt;end&lt;/span&gt; %&amp;gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;

&lt;p&gt;&lt;br/&gt;&lt;/p&gt;

&lt;p&gt;Well, how exactly will we verify that the view is indeed displaying the right products and suppressing the others?  We could manually test each scenario by visually inspecting the resulting UI, and that might be good enough for us to have confidence that the app is doing the right thing as of this moment.  But code has a life of its own, and it will grow and change over time, and we want automated tests to make sure that this page continues to display the correct data even after those inevitable changes.&lt;/p&gt;

&lt;p&gt;So we decide to write tests to verify that we&amp;#8217;re displaying only the right products.  And since this logic is inside our view template, we need to write tests that will render our view template and then dissect the resulting HTML to verify that it contains the products that should be present and that it does not contain the products that should not be present.  But in order to render the HTML, we need to invoke some controller action.  And because that lone &lt;code&gt;if&lt;/code&gt; statement needs at least four different test cases to check the various conditions, we get the joy of doing all that setup and dissection at least four times.  That&amp;#8217;s a big enough pain that it quickly becomes very tempting to let this bit of logic remain untested, remain out of sight of the coverage report, and remain &amp;#8220;good enough.&amp;#8221;&lt;/p&gt;

&lt;p&gt;We can do better than that.  When something&amp;#8217;s too hard to test, we should refactor it until it&amp;#8217;s easy to test. [1]&lt;/p&gt;

&lt;p&gt;We&amp;#8217;re going to need this logic outside of the view anyway, so the sooner we get it into the model the better.  Sure, the view will only display those products that are available for purchase, but we need that logic for server-side validation as well.  Before we process an order, we need to make sure that we still have the product in stock.  If we leave the logic in the view as is, then we&amp;#8217;ll be forced to duplicate that logic elsewhere inside our order-processing code.  There&amp;#8217;s clearly no justification at all for leaving this logic in the view.  &lt;/p&gt;

&lt;div class="dean_ch" style="white-space: wrap;"&gt;&lt;ol&gt;&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;lt;% &lt;span class="kw1"&gt;for&lt;/span&gt; product &lt;span class="kw1"&gt;in&lt;/span&gt; &lt;span class="re1"&gt;@products&lt;/span&gt; %&amp;gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;lt;% &lt;span class="kw1"&gt;if&lt;/span&gt; product.&lt;span class="me1"&gt;available_for_purchase&lt;/span&gt;? %&amp;gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;!&amp;#8211; display purchasable product here &amp;#8211;&amp;gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;!&amp;#8211; &amp;#8230; &amp;#8211;&amp;gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;lt;% &lt;span class="kw1"&gt;end&lt;/span&gt; %&amp;gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;lt;% &lt;span class="kw1"&gt;end&lt;/span&gt; %&amp;gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;

&lt;p&gt;&lt;br/&gt;&lt;/p&gt;

&lt;p&gt;When we encapsulate this logic in the &lt;code&gt;Product&lt;/code&gt; class itself, we can test that logic in &lt;em&gt;isolation&lt;/em&gt;, without any dependencies on controllers, and without the need for fragile HTML-parsing to verify the result.  Once we perform this refactoring, unit testing the &lt;code&gt;#available_for_purchase?&lt;/code&gt; method becomes trivial, &lt;em&gt;and&lt;/em&gt; we can refer to that method wherever necessary without unnecessary duplication.&lt;/p&gt;

&lt;p&gt;Better still, if we know that we only want to display the products that are available for purchase, we can ensure that our controller provides &lt;em&gt;only&lt;/em&gt; those products to the view in the first place.  With this approach, our view then enjoys the pleasant simplicity of just displaying the list of products.&lt;/p&gt;

&lt;div class="dean_ch" style="white-space: wrap;"&gt;&lt;ol&gt;&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;lt;% &lt;span class="kw1"&gt;for&lt;/span&gt; product &lt;span class="kw1"&gt;in&lt;/span&gt; &lt;span class="re1"&gt;@products&lt;/span&gt; %&amp;gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;lt;!&amp;#8211; display purchasable product here &amp;#8211;&amp;gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;lt;!&amp;#8211; &amp;#8230; &amp;#8211;&amp;gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;lt;% &lt;span class="kw1"&gt;end&lt;/span&gt; %&amp;gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;

&lt;p&gt;&lt;br/&gt;&lt;/p&gt;

&lt;p&gt;The coverage report isn&amp;#8217;t going to alert us to business logic lurking in our view templates.  It&amp;#8217;s up to us to keep our views from becoming &lt;a href="http://www.youtube.com/watch?v=ku3QkWcPSEw" title="YouTube - RailsEnvy MVC Public Service Announcement #3 - Keeping Views Stupid"&gt;too smart for their own good&lt;/a&gt;, and it&amp;#8217;s up to peer code reviews to keep us honest.&lt;/p&gt;

&lt;h2&gt;Raking for Buried Treasure&lt;/h2&gt;

&lt;p&gt;While it&amp;#8217;s tempting to let our views acquire too much business logic, there&amp;#8217;s usually an obvious place to &lt;em&gt;move&lt;/em&gt; that logic once we realize the error of our ways.  (In Rails, you&amp;#8217;ll typically relocate that logic to a model class or to a helper, either of which are easily tested in isolation.)  But what about the other parts of our application where untested code tends to hide out and germinate?&lt;/p&gt;

&lt;p&gt;Perhaps we have some code that only needs to run at application start-up.  In Rails, we&amp;#8217;re talking about code in &lt;code&gt;environment.rb&lt;/code&gt; or &lt;code&gt;config/initializers&lt;/code&gt;.  In Grails, &lt;code&gt;BootStrap.groovy&lt;/code&gt; is home to this logic.  In either case (or in most any other framework), we&amp;#8217;re not likely to see those start-up &amp;#8220;scripts&amp;#8221; included in the coverage report, nor is there a natural and obvious place for testing any complex code that we may need to include in the start-up process.  We&amp;#8217;re used to testing models and controllers and helpers and mailers, but where does this start-up logic fit into the mix?&lt;/p&gt;

&lt;p&gt;Data migration suffers from a similar problem.  Rails migrations are great for creating and dropping tables, adding and removing columns, etc., but sometimes we need to do more than just alter the schema; sometimes we want to push &lt;em&gt;data&lt;/em&gt; around as well.  Schema transformations are essentially declarative code, and really don&amp;#8217;t warrant anything beyond visual verification of the results.  But when it comes time to migrate 10 million records from some legacy database into our hip new application, chances are we&amp;#8217;re not just talking about simple declarations anymore.  What&amp;#8217;s the worst that could happen though?  This code only has to run once.  And who wants to write a bunch of tests for code that we&amp;#8217;re only gonna run once and then throw away?  And once again, there&amp;#8217;s no obvious place for us to add tests for this kind of data conversion functionality in the first place.  Surely a simple Rake task will suffice.&lt;/p&gt;

&lt;div class="dean_ch" style="white-space: wrap;"&gt;&lt;ol&gt;&lt;li class="li1"&gt;&lt;div class="de1"&gt;namespace &lt;span class="re3"&gt;:db&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; namespace &lt;span class="re3"&gt;:load&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; desc &lt;span class="st0"&gt;&amp;#8216;Load products from csv&amp;#8217;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; task &lt;span class="re3"&gt;:products&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw3"&gt;require&lt;/span&gt; &lt;span class="st0"&gt;&amp;#8216;csv&amp;#8217;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw3"&gt;require&lt;/span&gt; &lt;span class="st0"&gt;&amp;#8216;environment&amp;#8217;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; CSV.&lt;span class="kw3"&gt;open&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;&amp;quot;#{RAILS_ROOT}/db/input/csv/product-catalog/products.csv&amp;quot;&lt;/span&gt;, &lt;span class="st0"&gt;&amp;#8216;r&amp;#8217;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;.&lt;span class="me1"&gt;each_with_index&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt; |row, idx|&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;next&lt;/span&gt; &lt;span class="kw1"&gt;if&lt;/span&gt; row&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="nu0"&gt;0&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt; == &lt;span class="st0"&gt;&amp;quot;Product&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw3"&gt;p&lt;/span&gt; = Product.&lt;span class="me1"&gt;find_or_create_by_name&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;row&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="nu0"&gt;0&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw3"&gt;p&lt;/span&gt;.&lt;span class="me1"&gt;description&lt;/span&gt; = e.&lt;span class="me1"&gt;purpose&lt;/span&gt; = row&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="nu0"&gt;5&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw3"&gt;p&lt;/span&gt;.&lt;span class="me1"&gt;sku&lt;/span&gt; = row&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="nu0"&gt;3&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw3"&gt;p&lt;/span&gt;.&lt;span class="me1"&gt;price&lt;/span&gt; = row&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="nu0"&gt;4&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw3"&gt;p&lt;/span&gt;.&lt;span class="me1"&gt;save&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; shipping_options = row&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="nu0"&gt;1&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;.&lt;span class="kw3"&gt;split&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;&amp;quot;|&amp;quot;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; shipping_options.&lt;span class="me1"&gt;each&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt; |o|&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw3"&gt;p&lt;/span&gt;.&lt;span class="me1"&gt;shipping_options&lt;/span&gt; &amp;lt;&amp;lt; ShippingOption.&lt;span class="me1"&gt;find_by_name&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;o&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; vendors = row&lt;span class="br0"&gt;&amp;#91;&lt;/span&gt;&lt;span class="nu0"&gt;2&lt;/span&gt;&lt;span class="br0"&gt;&amp;#93;&lt;/span&gt;.&lt;span class="kw3"&gt;split&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;&amp;quot;|&amp;quot;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; vendors.&lt;span class="me1"&gt;each&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt; |v|&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw3"&gt;p&lt;/span&gt;.&lt;span class="me1"&gt;vendors&lt;/span&gt; &amp;lt;&amp;lt; Vendor.&lt;span class="me1"&gt;find_by_number&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;v&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt; &lt;span class="kw1"&gt;unless&lt;/span&gt; v.&lt;span class="me1"&gt;downcase&lt;/span&gt; == &lt;span class="st0"&gt;&amp;#8216;none&amp;#8217;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &lt;span class="kw1"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&lt;span class="kw1"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;

&lt;p&gt;&lt;br/&gt;&lt;/p&gt;

&lt;p&gt;Indeed, a &lt;em&gt;simple&lt;/em&gt; Rake task will suffice, but that&amp;#8217;s certainly not what we&amp;#8217;re looking at above.  While we &lt;em&gt;could&lt;/em&gt; write tests for this logic in its current state, doing so is unnecessarily difficult.  We&amp;#8217;d be restricted to solely black box tests.  To test each individual decision point, we&amp;#8217;re forced to also construct a new file holding the appropriate dataset, run the Rake task, and then inspect the state of the data in the database.  For &lt;em&gt;every&lt;/em&gt; decision point.  &lt;/p&gt;

&lt;h2&gt;Scripts Can Be Classy Too&lt;/h2&gt;

&lt;p&gt;We shouldn&amp;#8217;t have to also test the ability to read a file (i.e., line 7) just so that we can test the ability to populate a vendor based on a given vendor number (i.e., line 21).  For sure, we want one good end-to-end test to verify that all the cogs are working together correctly.  But if that&amp;#8217;s our sole testing strategy, then we&amp;#8217;ve made testing just painful enough that it probably won&amp;#8217;t happen at all.  &lt;/p&gt;

&lt;p&gt;Whether we&amp;#8217;re talking about hard-to-test code in start-up scripts, hard-to-test code in migration scripts, or hard-to-test code hiding out in the handful of other custom scripts that an application tends to accumulate over time, the answer&amp;#8217;s the same in each case.  Just because the coverage report doesn&amp;#8217;t see this hidden code doesn&amp;#8217;t mean that it&amp;#8217;s not worth testing.  And just because our framework-of-choice might not provide a convention for testing this logic, that doesn&amp;#8217;t mean that we should just punt.&lt;/p&gt;

&lt;p&gt;When something&amp;#8217;s too hard to test, we should refactor it until it&amp;#8217;s easy to test.  &lt;/p&gt;

&lt;div class="dean_ch" style="white-space: wrap;"&gt;&lt;ol&gt;&lt;li class="li1"&gt;&lt;div class="de1"&gt;namespace &lt;span class="re3"&gt;:db&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; namespace &lt;span class="re3"&gt;:load&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; desc &lt;span class="st0"&gt;&amp;#8216;Load products from csv&amp;#8217;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; task &lt;span class="re3"&gt;:products&lt;/span&gt; &lt;span class="kw1"&gt;do&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span class="kw3"&gt;require&lt;/span&gt; &lt;span class="st0"&gt;&amp;#8216;environment&amp;#8217;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; importer = ProductCsvImporter.&lt;span class="me1"&gt;new&lt;/span&gt;&lt;span class="br0"&gt;&amp;#40;&lt;/span&gt;&lt;span class="st0"&gt;&amp;quot;#{RAILS_ROOT}/db/input/csv/product-catalog/products.csv&amp;quot;&lt;/span&gt;&lt;span class="br0"&gt;&amp;#41;&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; importer.&lt;span class="me1"&gt;run&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &amp;nbsp; &lt;span class="kw1"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li1"&gt;&lt;div class="de1"&gt;&amp;nbsp; &lt;span class="kw1"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li class="li2"&gt;&lt;div class="de2"&gt;&lt;span class="kw1"&gt;end&lt;/span&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;

&lt;p&gt;&lt;br/&gt;&lt;/p&gt;

&lt;p&gt;In the case of this Rake task, and in each of the cases discussed above, by simply moving the logic out of the script and into a proper class (or module), the testing strategy goes from clumsy at best to downright obvious.  We no longer need to invoke the whole script in order to verify the particular unit of functionality that we want to test.  Instead, we test that functionality in isolation, and allow the script to resume its trivial role of merely calling our well-tested class.&lt;/p&gt;

&lt;h2&gt;Use It Wisely&lt;/h2&gt;

&lt;p&gt;In order to make effective use of coverage analysis, it&amp;#8217;s important for us to understand what a coverage report is telling us &lt;em&gt;and&lt;/em&gt; what it&amp;#8217;s incapable of telling us.  Tools are imperfect, but we can adopt strategies to make sure we&amp;#8217;re reaping the maximum benefit from the tools we choose to employ.  With good naming conventions and an agreed-upon application structure, we can easily configure an intelligent solution that allows the coverage tool to automatically pick up any new source files that we want included in the report.  With a commitment to testing all application logic - regardless of whether it&amp;#8217;s needed in a model, a view, a script, etc. - we&amp;#8217;ll extract the code that would otherwise be buried in a dark corner of our app.  We&amp;#8217;ll benefit from the ability to test it in isolation, and we&amp;#8217;ll allow the coverage tool to assess that code, giving us a more realistic and complete view of our codebase.&lt;/p&gt;

&lt;p&gt;Invisible code is hidden technical debt, but the sooner you expose it, the sooner you can start to pay it down.&lt;/p&gt;

&lt;h2&gt;Notes&lt;/h2&gt;

&lt;p&gt;[1]  In past posts in this series, I&amp;#8217;ve advocated test-driven development (TDD) as means for combatting the various testing anti-patterns. Invisible code is no exception.  While this post is geared more toward &lt;em&gt;uncovering&lt;/em&gt; invisible code so that we can give it the testing it deserves, developing test-first is the best bet for &lt;em&gt;preventing&lt;/em&gt; invisible code in the first place.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;This &lt;a href="http://jasonrudolph.com/blog/tag/testing-anti-patterns/" title="jasonrudolph.com/blog - Testing Anti-Patterns"&gt;series&lt;/a&gt; is taken from the &lt;a href="http://blog.thinkrelevance.com/2008/5/23/how-to-fail-with-100-test-coverage" title="Relevance Blog : How To Fail With 100% Test Coverage"&gt;How To Fail With 100% Test Coverage&lt;/a&gt; talk. Check the &lt;a href="http://thinkrelevance.com/events" title="Relevance: Events"&gt;schedule&lt;/a&gt; for a talk near you.&lt;/p&gt;

&lt;p&gt;&amp;#8211;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thanks&lt;/strong&gt; to &lt;a href="http://muness.blogspot.com/" title="Mundane Essays"&gt;Muness Alrubaie&lt;/a&gt;, &lt;a href="http://thinkrelevance.com/about/justin-gehtland" title="Relevance: Justin Gehtland"&gt;Justin Gehtland&lt;/a&gt;, and &lt;a href="http://gigavolt.net/blog/" title="Potential Differences"&gt;Greg Vaughn&lt;/a&gt; for reading drafts of this post.&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/jasonrudolph?a=KYLlIk"&gt;&lt;img src="http://feeds.feedburner.com/~f/jasonrudolph?i=KYLlIk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jasonrudolph?a=L29AxK"&gt;&lt;img src="http://feeds.feedburner.com/~f/jasonrudolph?i=L29AxK" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/jasonrudolph?a=zydDRk"&gt;&lt;img src="http://feeds.feedburner.com/~f/jasonrudolph?i=zydDRk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/jasonrudolph/~4/367967922" height="1" width="1"/&gt;</description>
      <pubDate>Mon, 18 Aug 2008 08:00:02 CDT</pubDate>
      <guid isPermaLink="true">http://jasonrudolph.com/blog/?p=191</guid>
      <dc:creator>Jason Rudolph</dc:creator>
    </item>
    <item>
      <title>Agile 2008 - Sanjiv Augustine - The effect of Agile Projects on Middle Management</title>
      <link>http://www.groovygrails.com/blog/robert_payne/2008/08/agile_2008__sanjiv_augustine__the_effect_of_agile_projects_on_middle_management.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>I talk with Sanjiv Augustine about his work with Agile Project/Portfolio Management and the Middle Managers that execute projects within organizations.  Sanjiv and I have worked together for years on client engagements, training and publishing.  More recently we have been working to kick off Agile Philanthropy.  LitheSpeed was the sponsor for the LiveAid Stage this year and you will be seeing more of Sanjiv and LitheSpeed in the years to come here on the Agile Toolkit Podcast.&#xD;
&lt;br /&gt;&#xD;
&lt;br /&gt;Enjoy.&#xD;
&lt;br /&gt;&#xD;
&lt;br /&gt;-bob payne</description>
      <pubDate>Sun, 17 Aug 2008 16:00:01 CDT</pubDate>
      <guid isPermaLink="true">http://agiletoolkit.libsyn.com/index.php?post_id=369243#</guid>
      <dc:creator>Bob Payne</dc:creator>
    </item>
    <item>
      <title>eRubyCon 2008 Day 2</title>
      <link>http://www.groovygrails.com/blog/josh_holmes/2008/08/erubycon_2008_day_2.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>&lt;p&gt;&#xD;
Yesterday I wrote a write up of &lt;a href="http://www.joshholmes.com/2008/08/15/eRubyCon2008Day1.aspx"&gt;eRubyCon&#xD;
2008 Day 1&lt;/a&gt;. &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a title="Erubycon" href="http://www.flickr.com/photos/86613980@N00/2770067004/"&gt;&#xD;
            &lt;img class="flickr" alt="Erubycon" hspace="5" src="http://static.flickr.com/3263/2770067004_23cfa89154_m.jpg" align="left" vspace="5" border="0"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt; -&#xD;
Charles Nutter started up with JRuby. I'm always impressed by people that are able&#xD;
to make their weekend project their full time job. I was further impressed that Charles&#xD;
was up with the rest of the speakers until closer to 4am than any of us should really&#xD;
admit, drinking really good scotch and solving the world's problems. &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Charles talked about the JVM and Java as both a problem and a great asset. There are&#xD;
a lot of people that look at the J in JRuby and automatically associate it with all&#xD;
of the things that they don't like about Java. Charles answer is to separate the JVM&#xD;
from the Java language. He did a really good job of talking about the things that&#xD;
the JVM brings over the standard Ruby runtimes such as world class garbage collection,&#xD;
memory compaction, thread handling and the like. He did a number of really compelling&#xD;
demos around threading in particular. One of the things that he said here is that&#xD;
JRuby and IronRuby are really the only Ruby implementations that are able to do native&#xD;
threads because they are the only ones that are built on production quality VMs that&#xD;
handle that native threading for them. &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a href="http://www.joshholmes.com/content/binary/WindowsLiveWriter/eRubyCon2008Day2_8792/0816080915_2.jpg"&gt;&#xD;
            &lt;img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; margin: 5px; border-right-width: 0px" height="184" alt="0816080915" src="http://www.joshholmes.com/content/binary/WindowsLiveWriter/eRubyCon2008Day2_8792/0816080915_thumb.jpg" width="244" align="right" border="0"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;One&#xD;
of the great quotes was "We write a lot of Java. So you don't have to..." - Charles&#xD;
Nutter&#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
After setting the stage, he pulled up a long list of features and said - "There's&#xD;
way too much for me to cover in the time left - what do you want to see?". that was&#xD;
fun. The first suggestion that he showed was 2D graphics that flashed a bunch of little&#xD;
balls around the screen. It was even responsive to voice commands. The second suggestion&#xD;
was to show Rails running on JRuby. He showed that they are running Rails on Ruby&#xD;
1.8.6 (java). Next he brought up image_voodoo to do more 2D libraries. Lastly, he&#xD;
showed "java_inline" which allows you to inline Java code similar to the Ruby_inline&#xD;
which allows you to inline C right in your Ruby code. &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
  - Evan Light came up next. Unfortunately I was putting out a few small fires.&#xD;
Fortunately Michael Lettere wrote up a small write up so that I could include it here. &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
Evan Light hates EJBs.&lt;br&gt;&#xD;
EJB encourages difficult to test idioms, private fields, private static final fields.&lt;br&gt;&#xD;
Nice demo code "public class DeepThought" &amp;lt;--- How do you test that?&lt;br&gt;&#xD;
You COULD shoot the guy who wrote it, but don't do that.&lt;br&gt;&#xD;
Very good use of humor, engaged the audience. &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a title="Stuart Halloway, Neal Ford" href="http://www.flickr.com/photos/86613980@N00/2770050696/"&gt;&#xD;
            &lt;img class="flickr" alt="Stuart Halloway, Neal Ford" hspace="5" src="http://static.flickr.com/3294/2770050696_e08e4b02bf_m.jpg" align="right" vspace="5" border="0"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt; -&#xD;
The lunch keynote was Neal Ford. Neil Ford is an amazing speaker. What’s cool about&#xD;
him is that every time I see him speaker, I wonder how he could get any better. And&#xD;
then he does. Today’s talk was about complexity. One of the core concepts that he&#xD;
talked about is the idea of Language Lockdown. It’s when language writers put in features&#xD;
to protect people from themselves and cut down on the stupid things that you can do.&#xD;
The idea is that if you do that the lower end (read cheaper) developers will still&#xD;
be productive. “What they are trying to do is strap a rocket to the ass of a turtle.&#xD;
What they are actually doing is putting chains on the rabbits than can go fast.”&lt;br&gt;&#xD;
The problem with that take though is two fold. First, it is not a linear line between&#xD;
the top developers and the lower end developers. What that means is that on the curve,&#xD;
a highly productive programmer will get done in one day what it will take an average&#xD;
developer more than a week to do and the weak developer a month or more. To point&#xD;
out the second issue, Neal quoted one of my other favorite speaker - “Bad developers&#xD;
will move heaven and earth to do the wrong thing” - Glenn Vanderburgh&lt;br&gt;&#xD;
One of the huge questions that he put out there is “How much of your enterprise software&#xD;
simple services accidental complexity?”. It’s a great question. &#xD;
&lt;br&gt;&#xD;
As he was wrapping up, he left us with the thought that “Courage is contagious. Cowardice&#xD;
is infectious”. &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a title="Stuart Halloway" href="http://www.flickr.com/photos/86613980@N00/2769207061/"&gt;&#xD;
            &lt;img class="flickr" alt="Stuart Halloway" hspace="5" src="http://static.flickr.com/3097/2769207061_9732021f41_m.jpg" align="left" vspace="5" border="0"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt;-&#xD;
Following Neal was Stuart Halloway again. He was talking this time about how one can&#xD;
fail with 100% test coverage. It’s an interesting topic because for so many people,&#xD;
100% test coverage is the holy grail that they shoot for. The first thing that he&#xD;
pointed out is that you might cover all the lines, but not all the branches so it&#xD;
depends on how you measure things to get to 100% coverage. The second thing that he&#xD;
points out is that you can cover all the code, but not all the corner cases. The example&#xD;
that he used is testing if a value is above or below $25.00 but forgetting $25.00&#xD;
even. Oops. Then you can start writing way too much code and too much complexity into&#xD;
your tests. Now you need to test your tests and you’ve taken too much time writing&#xD;
them. Then he talked about the “ugly mirror” where the test is really a mirror of&#xD;
the code where you’re covering the line but using the code that you are trying to&#xD;
test while testing – oh dear I have a headache. This is where he says that you are&#xD;
allowed to write literals in your tests. &#xD;
&lt;br&gt;&#xD;
Neal Ford piped in - “It’s ok for your test to be moist, not drenched”. &#xD;
&lt;br&gt;&#xD;
The next topic was slow tests and how dangerous they are. The short version of the&#xD;
issue is that if the unit tests don’t run in under 1 second, developers are not going&#xD;
to run them. Functional tests should run in under 2 minutes. If they don’t, then factor&#xD;
them so that they run on different schedules, parallelize them on different machines&#xD;
to get the normal check-in process back under the 2 minute mark if possible. &#xD;
&lt;br&gt;&#xD;
The last type of fail that he talked about is shallow tests. The quote that he referenced&#xD;
is “No automated test suite can ever replace exploratory testing.” - Jay Fields. The&#xD;
goal is that once the unit and functional testing passes, that people will put themselves&#xD;
in the clients seat and go spelunking and try out a bunch of stuff. &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
          &lt;a title="Joe O'Brien, Chris Nelson, Jim Weirich" href="http://www.flickr.com/photos/86613980@N00/2770056920/"&gt;&#xD;
            &lt;img class="flickr" alt="Joe O'Brien, Chris Nelson, Jim Weirich" hspace="5" src="http://static.flickr.com/3031/2770056920_5f56bd462b_m.jpg" align="right" vspace="5" border="0"&gt;&lt;/img&gt;&#xD;
          &lt;/a&gt; -&#xD;
The next talk was a very unique idea called “Dialogue Concerning the Two Chief Modeling&#xD;
Systems”. They wrote a play! The guys from EdgeCase, Joe O’Brien, Jim Weirich and&#xD;
Chris Nelson, acted out a normal project for them. They started out on twitter talking&#xD;
about the new project that they just landed. Then they actually started with the early&#xD;
on meetings that they have. Joe played the cowboy dev lead who insists that it’s a&#xD;
“simple rails app” and decides to do a data first model. Chris played clueless nub&#xD;
and Jim played the seasoned architect that was concerned about requirements analysis,&#xD;
separation of layers and behavior driven models. Joe, ready to start slamming code&#xD;
out, starts pairing with Chris. The first thing that they tackle is a simple calendar&#xD;
event. Then they have to schedule reoccuring events. Joe, the cowboy, just decides&#xD;
to replicate the events in order to do the reoccurence. The next requirement is rescheduling&#xD;
the reoccuring meetings.... Oops. They have neatly coded themselves into a corner&#xD;
and start hacking out a solution. At that point, Chris decided to take a walk and&#xD;
went to see what Jim thought of it all. Jim started writing out CRC cards and started&#xD;
thinking about higher level ideas, bringing in light-weight design patterns around&#xD;
temporal expressions from Martin Fowler and so on. Jim, the architect, is blithely&#xD;
ignoring “implementation details” such as where to store the data and performance.&#xD;
When performance sucked – they went back to the drawing board. Jim and Joe had to&#xD;
eventually come together. Of course the answer was to write a DSL... :)&lt;br&gt;&#xD;
Great talk. The good news is that Neal Ford is following them so there won’t be a&#xD;
let down as we end the day... &#xD;
&lt;/p&gt;&#xD;
        &lt;p&gt;&#xD;
- The last talk of the day was Neal Ford talking about Design Patterns in Ruby. One&#xD;
of the things that he pointed out fairly early on is that the Design Patterns book,&#xD;
even according to one of the authors ( Vlissides), should have been called “Making&#xD;
C++ Suck Less”. Even the Smalltalk that’s in the book was really C++ written in Smalltalk&#xD;
syntax. He covered a number of different patterns including the Iterator and the Interpretor&#xD;
pattern. There were a number of circumstances where he pointed out that the issues&#xD;
addressed by the pattern were addressed by the Ruby language. For example, the interpretor&#xD;
pattern’s intent is really addressed by DLSs which are dead easy to implement in Ruby.&#xD;
The only problem with this session is that it’s at the end of the day and my brain&#xD;
is a little mush at this point. &#xD;
&lt;/p&gt;&#xD;
        &lt;img width="0" height="0" src="http://www.joshholmes.com/aggbug.ashx?id=4ad4f70f-2af2-4e1b-884f-0ea2f6afd606"&gt;&lt;/img&gt;&#xD;
      &lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~f/JoshHolmes?a=YlcMnK"&gt;&lt;img src="http://feeds.feedburner.com/~f/JoshHolmes?i=YlcMnK" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/JoshHolmes?a=5w10ak"&gt;&lt;img src="http://feeds.feedburner.com/~f/JoshHolmes?i=5w10ak" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/JoshHolmes?a=PhIiAk"&gt;&lt;img src="http://feeds.feedburner.com/~f/JoshHolmes?i=PhIiAk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/JoshHolmes?a=kgHzdK"&gt;&lt;img src="http://feeds.feedburner.com/~f/JoshHolmes?i=kgHzdK" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~f/JoshHolmes?a=QkInqk"&gt;&lt;img src="http://feeds.feedburner.com/~f/JoshHolmes?i=QkInqk" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/JoshHolmes/~4/367267181" height="1" width="1"/&gt;</description>
      <pubDate>Sun, 17 Aug 2008 13:00:02 CDT</pubDate>
      <guid isPermaLink="true">http://www.joshholmes.com/PermaLink,guid,4ad4f70f-2af2-4e1b-884f-0ea2f6afd606.aspx</guid>
      <dc:creator>Josh Holmes</dc:creator>
    </item>
    <item>
      <title>Dan Pritchett on Availability</title>
      <link>http://www.groovygrails.com/blog/michael_nygard/2008/08/dan_pritchett_on_availability.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>&lt;p&gt;&lt;a href="http://www.linkedin.com/in/driveawedge"&gt;Dan Pritchett&lt;/a&gt; is a man after my own heart. His &lt;a href="http://www.addsimplicity.com/adding_simplicity_an_engi/2008/08/availability-en.html"&gt;latest post&lt;/a&gt; talks about the path to availability enlightenment. The obvious path--reliable components and vendor-supported commercial software--leads only to tears.&lt;/p&gt;&lt;p&gt;You can begin on the path to enlightenment when you set aside dreams of perfect software running on perfect hardware, talking over perfect networks. Instead, embrace the reality of fallible components. Don't design around them, design for them. &lt;/p&gt;&lt;p&gt;How do you design for failure-prone components? That's what most of &lt;a href="http://www.amazon.com/gp/product/0978739213?ie=UTF8&amp;amp;tag=michaelnygard-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0978739213"&gt;Release It!&lt;/a&gt; is all about. &lt;br /&gt;&lt;/p&gt;</description>
      <pubDate>Sun, 17 Aug 2008 11:00:01 CDT</pubDate>
      <guid isPermaLink="true">http://www.michaelnygard.com/blog/2008/08/dan_pritchett_on_availability.html</guid>
      <dc:creator>Michael Nygard</dc:creator>
    </item>
    <item>
      <title>Storytelling</title>
      <link>http://www.groovygrails.com/blog/alex_miller/2008/08/storytelling.html?utm_source=blogitem&amp;utm_medium=rss&amp;utm_campaign=blogrss</link>
      <description>&lt;p&gt;I&amp;#8217;ve been taking a lot of walks lately and listening to podcasts, and I&amp;#8217;ve become kind of addicted to podcasts oriented around story-telling.  Perhaps the best is &lt;a href="http://thislife.org"&gt;This American Life with Ira Glass&lt;/a&gt;.  This &lt;a href="http://npr.org"&gt;NPR&lt;/a&gt; series every week takes a theme and tells a series of stories around it.  They do an amazing job of putting together a riveting show every week.  You can subscribe on iTunes but to reduce bandwidth they only provide the most recent episode.&lt;/p&gt;
&lt;p&gt;Last week&amp;#8217;s episode &lt;a href="http://thislife.org/Radio_Episode.aspx?episode=361"&gt;&amp;#8220;Fear of Sleep&amp;#8221;&lt;/a&gt; featured a number of good stories, but the one that stood out for me was &lt;a href="http://www.birbigs.com"&gt;Mike Birbiglia&amp;#8217;s&lt;/a&gt; stories about him acting out his dreams.  For one, it&amp;#8217;s really funny, as only extended personal stories can be.  For another, the presentation is just pitch-perfect - the pauses, the word choice, the pacing, etc.  Of course, the comedian background should make this no surprise.&lt;/p&gt;
&lt;p&gt;Of course, Mike&amp;#8217;s performance was actually taken from a show at &lt;a href="http://www.themoth.org/"&gt;The Moth&lt;/a&gt;, which I&amp;#8217;ve never heard of before.  Apparently, they do storytelling shows in both New York and LA.  Even better, they have a &lt;a href="http://www.themoth.org/podcast"&gt;podcast&lt;/a&gt;. :)  So, now I&amp;#8217;ve been working my way through their podcast and enjoying it immensely.&lt;/p&gt;
&lt;p&gt;Anyone else have any favorite story podcasts to share?
&lt;/p&gt;</description>
      <pubDate>Sun, 17 Aug 2008 08:00:02 CDT</pubDate>
      <guid isPermaLink="true">http://tech.puredanger.com/2008/08/16/storytelling/</guid>
      <dc:creator>Alex Miller</dc:creator>
    </item>
  </channel>
</rss>

