<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>DAVEBLOG 5000</title>
	
	<link>http://www.naildrivin5.com/daveblog5000</link>
	<description>Stuff that happens to Dave</description>
	<lastBuildDate>Sat, 17 Oct 2009 18:17:35 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/daveblog5000" /><feedburner:info uri="daveblog5000" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>My blog has moved</title>
		<link>http://feedproxy.google.com/~r/daveblog5000/~3/ud7S1x_3czI/</link>
		<comments>http://www.naildrivin5.com/daveblog5000/?p=191#comments</comments>
		<pubDate>Sat, 17 Oct 2009 18:17:35 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.naildrivin5.com/daveblog5000/?p=191</guid>
		<description><![CDATA[I&#8217;ve moved my blog over to jekyll, but keeping this here so that links still work.  Please update your RSS feeds.
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.naildrivin5.com/blog">I&#8217;ve moved my blog over to jekyll</a>, but keeping this here so that links still work.  Please update your RSS feeds.</p>
<img src="http://feeds.feedburner.com/~r/daveblog5000/~4/ud7S1x_3czI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.naildrivin5.com/daveblog5000/?feed=rss2&amp;p=191</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.naildrivin5.com/daveblog5000/?p=191</feedburner:origLink></item>
		<item>
		<title>My own personal tour of Scala</title>
		<link>http://feedproxy.google.com/~r/daveblog5000/~3/fE1SM_PNlq8/</link>
		<comments>http://www.naildrivin5.com/daveblog5000/?p=186#comments</comments>
		<pubDate>Fri, 11 Sep 2009 00:33:27 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://www.naildrivin5.com/daveblog5000/?p=186</guid>
		<description><![CDATA[So, the Main Scala Website has a &#8220;tour&#8221; of the features of Scala.  I liked the idea, but found a lot of the examples and descriptions a bit terse and uninspiring (some of them are downright confusing).  However, I really wanted to learn about these features.  So, I set about understanding each [...]]]></description>
			<content:encoded><![CDATA[<p>So, the <a href="http://www.scala-lang.org">Main Scala Website</a> has a &#8220;tour&#8221; of the features of Scala.  I liked the idea, but found a lot of the examples and descriptions a bit terse and uninspiring (some of them are downright confusing).  However, I really wanted to learn about these features.  So, I set about understanding each feature, trying to answer the question &#8220;What problem does this solve?&#8221;.  The results are here at <a href="http://www.naildrivin5.com/scalatour">www.naildrivin5.com/scalatour</a>.  This site was constructed using my homebrew wiki software, <a href="http://github.com/davetron5000/halen/tree/master">Halen</a> (which I created to test out my <a href="http://github.com/davetron5000/gliffy/tree/master">Gliffy Ruby client</a>).
</p>
<p>
It was a fun experience.  As someone coming from Java application development (and who knows enough Ruby to feel some pain in Java), I tried hard to map the features to real-world problems a &#8220;blue-collar developer&#8221; might be facing.  A lot of Scala enthusiasts seem to be functional programming nerds, and I know FP can turn a lot of people off.  I think Scala is a great way to learn and appreciate functional programming without having to swallow a huge amount of info at once.  So, I figured approaching Scala&#8217;s features from a different angle would be useful.
</p>
<p>
I <b>did</b> have to supplement my learning with info from Odersky&#8217;s awesome <a href="http://www.amazon.com/Programming-Scala-Comprehensive-Step-step/dp/0981531601/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1252628682&#038;sr=8-1">Programming Scala</a> book, but most of what I learned, I learned by playing around with code; all the code on the site should compile and run (at least in Scala 2.7.x).  The coolest thing was that by &#8220;touring&#8221; all of Scala&#8217;s (often weird) features, I got a good feel for how they all fit together.  The language feels like a very elaborate Rube-Goldberg Machine that ends up being rather elegant.  I feel that instead of casting Scala as a functional language, or a hybrid language, I would say that Scala is &#8220;static typing done right (or as right as is possible)&#8221;.
</p>
<p>The way Scala allows for <a href="http://www.naildrivin5.com/scalatour/wiki_pages/DuckTyping">duck typing</a>, for example, is really cool, and something I think Ruby code could benefit from.<br />
Stuff like <a href="http://www.naildrivin5.com/scalatour/wiki_pages/TypeVariance">type variance</a> is pretty heavy stuff, but when you dig into, and understand how functions are implemented, it ends up making some sense.  I even found a &#8220;real world&#8221; use for <a href="http://www.naildrivin5.com/scalatour/wiki_pages/ExplcitlyTypedSelfReferences">explictly-typed self-references</a>, which I thought was actually a sick joke for a while  :) Anyway, I hope that what I&#8217;ve learned doing this will be helpful to others.</p>
<img src="http://feeds.feedburner.com/~r/daveblog5000/~4/fE1SM_PNlq8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.naildrivin5.com/daveblog5000/?feed=rss2&amp;p=186</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.naildrivin5.com/daveblog5000/?p=186</feedburner:origLink></item>
		<item>
		<title>Intro to Scala for Java Developers – slides</title>
		<link>http://feedproxy.google.com/~r/daveblog5000/~3/vj3uBf9BIcg/</link>
		<comments>http://www.naildrivin5.com/daveblog5000/?p=179#comments</comments>
		<pubDate>Mon, 17 Aug 2009 13:44:28 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://www.naildrivin5.com/daveblog5000/?p=179</guid>
		<description><![CDATA[
Thought I&#8217;d post the slides of a talk I gave at work on Scala.  We&#8217;re primarily a Java shop, and every week we do either a code review or a tech-related presentation.


Our domain at work is analyzing residential energy data, so the examples herein are tailored to that:


 Read or Meter Read &#8211; Some [...]]]></description>
			<content:encoded><![CDATA[<p>
Thought I&#8217;d post the slides of a talk I gave at work on Scala.  We&#8217;re primarily a Java shop, and every week we do either a code review or a tech-related presentation.
</p>
<p>
Our domain at work is analyzing residential energy data, so the examples herein are tailored to that:
</p>
<ul>
<li> <b>Read</b> or <b>Meter Read</b> &#8211; Some amount of energy used over a period, e.g. &#8220;100kwh in the month of June&#8221;</li>
<li> <b>Service Point</b> &#8211; meta-data about an electric meter (the &#8220;point&#8221; at which &#8220;service&#8221; is available).
</ul>
<p>
I also omitted a code demo where I refactored part of our codebase into Scala to show the difference (trust me, it was awesome!).
</p>
<div style="width:425px;text-align:left" id="__ss_1856620"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/davetron5000/scala-for-java-developers-intro" title="Scala for Java Developers - Intro">Scala for Java Developers &#8211; Intro</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=scala-090813141457-phpapp02&#038;stripped_title=scala-for-java-developers-intro" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=scala-090813141457-phpapp02&#038;stripped_title=scala-for-java-developers-intro" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">documents</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/davetron5000">David Copeland</a>.</div>
</div>
<img src="http://feeds.feedburner.com/~r/daveblog5000/~4/vj3uBf9BIcg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.naildrivin5.com/daveblog5000/?feed=rss2&amp;p=179</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.naildrivin5.com/daveblog5000/?p=179</feedburner:origLink></item>
		<item>
		<title>Simple Metrics for Team and Process Improvement</title>
		<link>http://feedproxy.google.com/~r/daveblog5000/~3/_ji7G7FmG3g/</link>
		<comments>http://www.naildrivin5.com/daveblog5000/?p=159#comments</comments>
		<pubDate>Mon, 29 Jun 2009 20:35:27 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[metrics]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[reviews]]></category>

		<guid isPermaLink="false">http://www.naildrivin5.com/daveblog5000/?p=159</guid>
		<description><![CDATA[Recently, the development team where I work has started collecting bona-fide metrics, based on our ticketing system.  So few development shops (especially small ones) collect real information on how they work that it&#8217;s exciting that we&#8217;re doing it.

Here&#8217;s what we&#8217;re doing:

Number of releases during QA (we do a daily release, so more than daily [...]]]></description>
			<content:encoded><![CDATA[<p>Recently, the development team where I work has started collecting bona-fide metrics, based on our ticketing system.  So few development shops (especially small ones) collect real information on how they work that it&#8217;s exciting that we&#8217;re doing it.</p>
<p><p>
Here&#8217;s what we&#8217;re doing:</p>
<ul>
<li><b>Number of releases during QA</b> (we do a daily release, so more than daily is an indicator)</li>
<li><b>Defects found, by severity and priority</b></li>
<li><b>Average time from accepting a ticket (starting work) to resolving it (sending it for testing)</b></li>
<li><b>Number of re-opens</b> (i.e. a defect was sent to testing, but not fixed)</li>
<li><b>Average time from resolving to closing</b> (i.e. testing the fix)</li>
<li><b>Defects due to coding errors vs. unclear requirements</b> (this is really great to be able to collect; with our company so new and small, we can introduce this and <b>use</b> it without ruffling a lot of feathers)</li>
</ul>
<p>
The tricky thing about metrics is that they are not terribly meaningful by themselves; rather they indicate areas for focussed investigation.  For example, if it takes an average of 1 day to resolve a ticket, but 3 days to test and close it, we don&#8217;t just conclude that testing is inefficient; we have to investigate why.  Perhaps we don&#8217;t have enough testers.  Perhaps our testing environment isn&#8217;t stable enough.  Perhaps there are too many show-stoppers that put the testers on the bench while developers are fixing them.
</p>
<p>
Another way to interpret these values is to watch them over time.  If the number of critical defects is decreasing, it stands to reason we&#8217;re doing a good job.  If the number of re-opens is increasing, we are packing too much into one iteration and possibly not doing sufficient requirements analysis.  We <b>just</b> started collecting these on the most recent iteration, so in the coming months, it will be pretty cool to see what happens.
</p>
<p>
These metrics are pretty basic, but it&#8217;s great to be collecting them.  The one thing that can make hard-core analysis of these numbers (esp. over time as the team grows and new projects are created) is the lack of normalization.  If we introduced twice as many critical bugs this iteration than last, are we necessarily &#8220;doing worse&#8221;?  What if the requirements were more complex, or the code required was just&#8230;bigger?</p>
<p>
Normalizing factors like cyclomatic complexity, lines of code, etc, can shed some more light on these questions.  These normalizing factors aren&#8217;t always popular, but interpreted the right way, could be very informative.  We&#8217;re the same team, using the same language, working on the same product.  If iteration 14 adds 400 lines of code, with 3 critical bugs, but iteration 15 adds 800 lines of code with 4 critical bugs, I think we can draw some real conclusions (i.e. we&#8217;re getting better).
</p>
<p>
Another interesting bit of data would be to incorporate our weekly code review.  We typically review fresh-but-not-too-fresh code, mostly for knowledge sharing and general &#8220;architectural consistency&#8221;.  If we were to actively review code in development, before it is sent to testing, we could then have real data on the effectiveness of our code reviews.  Are we finding lots of coding errors at testing time?  Maybe more code reviews would help?  Are we finding fewer critical bugs in iteration 25, than in iteration 24 and 23, where we weren&#8217;t doing reviews?  Reviews helped a lot.
</p>
<p>
These are actually really simple things to do (especially with a small, cohesive team), and can shed real light on the development process.  What else can be done?</p>
<img src="http://feeds.feedburner.com/~r/daveblog5000/~4/_ji7G7FmG3g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.naildrivin5.com/daveblog5000/?feed=rss2&amp;p=159</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.naildrivin5.com/daveblog5000/?p=159</feedburner:origLink></item>
		<item>
		<title>Stand While You Work!</title>
		<link>http://feedproxy.google.com/~r/daveblog5000/~3/NBblLvogORk/</link>
		<comments>http://www.naildrivin5.com/daveblog5000/?p=140#comments</comments>
		<pubDate>Sat, 20 Jun 2009 17:01:27 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[desks]]></category>
		<category><![CDATA[jerker]]></category>
		<category><![CDATA[utby]]></category>

		<guid isPermaLink="false">http://www.naildrivin5.com/daveblog5000/?p=140</guid>
		<description><![CDATA[
After experiencing some back troubles recently, I was encouraged to work standing up.  The pain relief was immediate, and for the past several months, it&#8217;s been great.  I work most of the time standing, sitting for a few minutes if I get a bit tired.  Not only is this great for my [...]]]></description>
			<content:encoded><![CDATA[<p>
After experiencing some back troubles recently, I was encouraged to work standing up.  The pain relief was immediate, and for the past several months, it&#8217;s been great.  I work most of the time standing, sitting for a few minutes if I get a bit tired.  Not only is this great for my back, but it ensures I don&#8217;t work insane hours&#8230;I simply can&#8217;t stand for more than 8 hours a day.  When I first brought the subject of standing up with my company&#8217;s office manager, she was open to whatever I wanted to do; I figured since it&#8217;s my issue to solve (and since I wasn&#8217;t yet sold on the idea), I&#8217;d make do with something and bring it in.
</p>
<p>
While Joel Spolsky outfits his offices with <a href="http://www.joelonsoftware.com/items/2008/06/06.html">super fancy motorized</a> desks that can go from standing to sitting with the flick of a switch, those desks were <b>way</b> out of my price range.  Further, fixed height desks were also quite expensive (much like the word &#8220;wedding&#8221;, attaching the word &#8220;ergonominc&#8221; to something seems to double its price).  Enter the <a href="http://www.ikea.com/us/en/catalog/products/S49843462">Ikea Utby</a>!  The perfect size and perfect height, it looks great and was under $200!
</p>
<p><img style="margin: 5px" src="http://farm3.static.flickr.com/2451/3650774505_0354e3c061_m.jpg" height="200" align="left"/> </p>
<p>
Some might think it&#8217;s a bit small, but I find the more space I have, the bigger mess I make.  The Utby is, for me, the perfect amount of space.  Though, it&#8217;s so cheap, you could get two of them and make an awesome corner desk.  I work from home on occasion and also work on side projects after work.  Until recently I enjoyed the venerable (and, sadly, discontinued), <a href="http://adam.pra.to/content/jerker/">Ikea Jerker</a>. Last week, however, I was home recovering from back surgery, and was forbade by the doctor from sitting down.  I had to use my own makeshift stand up desk out of a keyboard stand and ironing board.  Pretty ghetto.<br />
<img style="margin: 5px" src="http://farm4.static.flickr.com/3616/3650774551_1842148101_m.jpg" height="200" align="right" /></p>
<p>
So, the Jerker is now in pieces and has been replaced by a second Utby at home.<a href="http://www.flickr.com/photos/davetron5000/3643630703/"><img style="margin: 5px" src="http://farm4.static.flickr.com/3313/3643630703_b3e58ae5ae_m.jpg" align="left" border="0"/></a>  The sitting problem, both at home and at work is simple: a bar chair.  I&#8217;ve got some plush comfy ones at home and bought a (reasonably) cheap <a href="http://www.ikea.com/us/en/catalog/products/S49850179">Henriksdal</a> for work.  So, for less than $300, I have a nice looking desk at which I can stand or sit, and should have continued good back health.  Even if you don&#8217;t have back problems, I highly recommend standing; it keeps me alert and focused and feels great.  You just have to make sure you have comfortable shoes.</p>
<img src="http://feeds.feedburner.com/~r/daveblog5000/~4/NBblLvogORk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.naildrivin5.com/daveblog5000/?feed=rss2&amp;p=140</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.naildrivin5.com/daveblog5000/?p=140</feedburner:origLink></item>
		<item>
		<title>Lead or Bleed</title>
		<link>http://feedproxy.google.com/~r/daveblog5000/~3/IwxwV6uVgWo/</link>
		<comments>http://www.naildrivin5.com/daveblog5000/?p=133#comments</comments>
		<pubDate>Mon, 25 May 2009 20:49:42 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Computers]]></category>

		<guid isPermaLink="false">http://www.naildrivin5.com/daveblog5000/?p=133</guid>
		<description><![CDATA[
After reading all of The Passionate Programmer over a week or so, I&#8217;m going back through and looking at some of the &#8220;Act On It!&#8221; sections, where Chad Fowler recommends specific actions to kickstart/sustain/boost your career.  The very first one, titled &#8220;Lead or Bleed?&#8221; suggests making a map of technologies, with &#8220;on the way [...]]]></description>
			<content:encoded><![CDATA[<p>
After reading all of <a href="http://pragprog.com/titles/cfcar2/the-passionate-programmer">The Passionate Programmer</a> over a week or so, I&#8217;m going back through and looking at some of the &#8220;Act On It!&#8221; sections, where Chad Fowler recommends specific actions to kickstart/sustain/boost your career.  The very first one, titled &#8220;Lead or Bleed?&#8221; suggests making a map of technologies, with &#8220;on the way out&#8221; on the left side and &#8220;bleeding edge&#8221; on the right side, then highlighting how well you know each thing.  Here&#8217;s my stab at it:
</p>
<p>
<img src="http://www.naildrivin5.com/daveblog5000/wp-content/technologies.png" alt="Technololgies: Lead or Bleed" title="Technololgies: Lead or Bleed" width="610" height="557" class="alignnone size-full wp-image-135" />
</p>
<p>
Green are things are know really well; yellow are things I could do at a job but am by no means an expert.
</p>
<p>
Obviously this is shaped by my own reality and what I perceive on the &#8216;net, and I omitted things like &#8220;C&#8221;, &#8220;UNIX&#8221; and &#8220;Windows&#8221;, because those are not really &#8220;on the way out&#8221; in the same way that C++ is (or that COBOL was, etc.).</p>
<img src="http://feeds.feedburner.com/~r/daveblog5000/~4/IwxwV6uVgWo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.naildrivin5.com/daveblog5000/?feed=rss2&amp;p=133</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.naildrivin5.com/daveblog5000/?p=133</feedburner:origLink></item>
		<item>
		<title>Learning Cucumber – With Dynamic types must come documentation</title>
		<link>http://feedproxy.google.com/~r/daveblog5000/~3/1ccztc2M9r4/</link>
		<comments>http://www.naildrivin5.com/daveblog5000/?p=123#comments</comments>
		<pubDate>Thu, 21 May 2009 13:25:49 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[webrat]]></category>

		<guid isPermaLink="false">http://www.naildrivin5.com/daveblog5000/?p=123</guid>
		<description><![CDATA[
Finally pulled the trigger on Cucumber, which allows one to write human-readable &#8220;features&#8221; that are essentially acceptance test cases.  You can then execute them by adding some glue code in a mish-mash of Ruby DSLs and verify functionality.


It took me quite a while to decide to get going on this because the examples and [...]]]></description>
			<content:encoded><![CDATA[<p>
Finally pulled the trigger on <a href="http://www.cukes.info">Cucumber</a>, which allows one to write human-readable &#8220;features&#8221; that are essentially acceptance test cases.  You can then execute them by adding some glue code in a mish-mash of Ruby DSLs and verify functionality.
</p>
<p>
It took me quite a while to decide to get going on this because the examples and documentation that are available are extremely hypothetical and very hand-wavy.  A lot of the information glosses over the fact that you are <b>still writing code</b> and you still need to know <b>what the keywords are</b> and <b>what data you will be given</b>.   Arcane non-human-readable symbols are almost preferable when getting started, because you don&#8217;t get distracted by English.  This is why Applescript drives me insane.
</p>
<p>
At any rate, I found <a href="http://themomorohoax.com/2009/03/08/rails-machinist-tutorial-machinist-with-cucumber-in-10-minutes">this page</a>, which was pretty helpful.  It shows testing a rails app using, among other things, <a href="http://github.com/brynary/webrat/tree/master">webrat</a> (another tool severely lacking in documentation but that is, nonetheless, pretty awesome).
</p>
<p>I&#8217;m writing a basic wiki (for science) and so I thought a good feature would be &#8220;home page shows all pages in sorted order&#8221;, so I wrote it up:</p>
<pre name="code">
Feature: pages are sorted
 As anyone
 The pages should be listed on the home page in sorted order

 Scenario: Visit Homepage
   As anyone
   When I visit the homepage
   Then The list of pages should be sorted
</pre>
<p>Now, the webrat/cucumber integration provided by rails means that the &#8220;plain English&#8221; has to actually conform to a subset of phrasing and terminology or you have to write the steps yourself (the features are everything under &#8220;Scenario&#8221;).  It&#8217;s not hard to do that, and it&#8217;s not hard to modify the default webrat steps, but it was a distraction intially.
</p>
<p>
Next up, you implement the steps and here is where the crazy intersection of Ruby DSLs really made things difficult.  The first two steps were pretty easy (&#8221;anyone&#8221; didn&#8217;t require any setup, and webrat successfully handled &#8220;When I visit the homepage&#8221;):</p>
<pre name="code" class="ruby">
Then /The list of pages should be sorted/ do
  response.should # I have no clue wtf to do here
end
</pre>
<p>A <tt>puts response.class</tt> and a puts <tt>response.methods</tt> gave me no useful information.  I eventually deduced that since Cucumber is a successor/add-on/something to RSpec, perhaps <tt>should</tt> comes from RSpec.  This takes a <tt>Matcher</tt> and webrat provides many.  Specifically, <tt>have_selector</tt> is available that allows selecting HTML elements based on the DOM.</p>
<pre name="code" class="ruby">
Then /The list of pages should be sorted/ do
  response.should have_selector("ul.pages")
end
</pre>
<p><b>Success!</b> (sort of).  My feature executing is all green, meaning the home page contains &lt;ul class=&#8221;pages&#8221;&gt;.  <tt>have_selector</tt> also takes a block (totally undocumented as to what it is or does in the webrat documentation):</p>
<pre name="code" class="ruby">
Then /The list of pages should be sorted/ do
  response.should have_selector("ul.pages") do |pages|
    # WTF is pages and what can I do with it?
  end
end
</pre>
<p>A <tt>puts pages.class</tt> later and I realize this is a Nokogiri <tt>NodeSet</tt>.    Now, I&#8217;m in business, though it would&#8217;ve been nice to be told WTF some of this stuff was and what I can/should do with it.  At this point it was pretty trivial to select the page names from my HTML and check if they are sorted:</p>
<pre name="code" class="ruby">
response.should have_selector('ul.pages') do |pages|
   page_names = []
   pages.should have_selector('li') do |li|
     li.should have_selector('.pagename') do |name|
       name.each do |one_name|
         page_names << one_name.content
       end
     end
   end
   assert_equal page_names,page_names.sort
   true
 end
</pre>
<p>(For some reason <tt>assert_equal</tt> doesn't evaluate to true when it succeeds and the block evaluates to false and then Cucumber/RSpec/Webrat/Ruby Gods claim my page is missing the <tt>ul</tt> tag).  My initial implementation walked the DOM using Nokogiri's  API directly, because I didn't realize that <tt>should</tt> had been mixed in (on?) to the objects I was being given.  I'm still not sure if using that is the intention, but it seemed a bit cleaner to me.
</p>
<p>
So, this took me a couple of hours, mostly  because of a combination of dynamic typing and lack of documentation.  I'm all for dynamic typing, and I totally realize that these are free tools and all that.  I think if the Ruby community (and the dynamic typing community in general) wants to succeed and make a case that dynamic typing, DSLs, meta-programming and all this (admittedly awesome and powerful) stuff enhance productivity, there <b>has to be documentation</b> as to the types of user-facing objects.
</p>
<p>
Now, given <a href="http://www.github.com">Github</a>'s general awesomeness, I'm totally willing to fork a repo, beef up the rdoc and request a pull, however I'm not even sure <b>whose</b> RDoc I could update to make this clear.  Just figuring out that the <tt>have_selector</tt> in <tt>response.should have_selector</tt> is part of webrat was nontrivial (I had to just guess that <tt>should</tt> was part of RSpec and that the <tt>Webrat::Matchers</tt> module was mixed in).  This is a problem and it's not clear to me how to solve it.
</p>
<p>
That being said, I was then able to create three more features using this system in about 10 minutes, so overall, I'm really happy with how things are working.  Certainly if this were Java, I'd still be feeding XML to maven or futzing with missing semicolons.  So, it's a net win for me.</p>
<img src="http://feeds.feedburner.com/~r/daveblog5000/~4/1ccztc2M9r4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.naildrivin5.com/daveblog5000/?feed=rss2&amp;p=123</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.naildrivin5.com/daveblog5000/?p=123</feedburner:origLink></item>
		<item>
		<title>Why maven drives me absolutely batty</title>
		<link>http://feedproxy.google.com/~r/daveblog5000/~3/Ix2CJV6zkpU/</link>
		<comments>http://www.naildrivin5.com/daveblog5000/?p=111#comments</comments>
		<pubDate>Wed, 13 May 2009 14:36:51 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[maven]]></category>

		<guid isPermaLink="false">http://www.naildrivin5.com/daveblog5000/?p=111</guid>
		<description><![CDATA[Although my maven bitching has been mostly snarky, I have come to truly believe it is the wrong tool for a growing enterprise and, like centralized version control, will lead to a situation where tools dictate process (and design).


But, what is maven actually good at?

Maven is great for getting started &#8212; you don&#8217;t have author [...]]]></description>
			<content:encoded><![CDATA[<p>Although my <a href="http://softwarefail.tumblr.com/tagged/maven">maven bitching</a> has been mostly snarky, I have come to truly believe it is the wrong tool for a growing enterprise and, like centralized version control, will lead to a situation where tools dictate process (and design).
</p>
<p>
But, what is maven actually good at?</p>
<ul>
<li>Maven is great for getting started &#8212; you don&#8217;t have author an ant file (or copy one from an existing project)</li>
<li>Maven is great for enforcing a standard project structure &#8212; if you always use maven, your projects always look the same</li>
</ul>
<p>This is about where it ends for me; everything else maven does &#8211; manage dependencies, automated process, etc., is done much better and much more quickly by other technology.  It&#8217;s pretty amazing that someone can make a tool worse than ant, but maven is surely it
</p>
<h4>Dependency management is not a build step</h4>
<p>
Maven is the equivalent of doing a <tt>sudo gem update</tt> everytime you call <tt>rake</tt>, or doing a <tt>sudo yum update</tt> before running <tt>make</tt>.  That&#8217;s just insane.  While automated dependency management is a key feature of a sophisticated development process, this is <b>a separate process</b> from developing my application.
</p>
<h4>Maven&#8217;s configuration is incredibly verbose</h4>
<p>It requires <b>36 lines</b> of human-readable XML to have my webapp run during integration tests. <b>Thirty Six</b>!  It requires <b>six lines</b> just to state a dependency.  Examining a maven file and tying to figure out where you are in its insane hierarchy is quite difficult.  It&#8217;s been pretty well-established outside the Java community that XML is horrible configuration file format; formats like YAML have a higher signal to noise ration, and using (gasp) actual scripting language code can be even more compact (and readable and maintainable).
</p>
<h4>The jars you use are at the mercy of Maven</h4>
<p>
If you want to use a third-party library, and maven doesn&#8217;t provide it (or doesn&#8217;t provide the version you need), you have to set up your own maven repo.  You then have to include that repo in your pom file, or in every single developer&#8217;s local maven settings.  If you secure your repo?  More XML configuration (and, until the most recent version, you had to have your password in cleartext&#8230;<b>in a version 2 application</b>).  The fallout here is that you will tend to stick with the versions available publicly, and we see how well that worked out for Debian.
</p>
<h4>Modifying default behavior is very difficult</h4>
<p>
Since maven is essentially a very, very high-level abstraction, you are the mercy of the plugin developers as to what you can do.  For example, it is not possible to run your integration tests through Cobertura.  The plugin developers didn&#8217;t provide this and there&#8217;s no way to do it without some major hacking of your test code organization and pom file.  This is bending your process to fit a tool&#8217;s shortcoming.  This is limitation designed into maven. This is fundamentally different that &#8220;opinionated software&#8221; like Rails; Rails doesn&#8217;t punish you so harshly for wanting to tweak things; maven makes it very difficult (or impossible).  There was no thought given in Maven&#8217;s design to using non-default behavior.
</p>
<h4>Extending Maven requires learning a plugin API</h4>
<p>While you can throw in random Ant code into maven, the only way to create re-usable functionality is to learn a complex <a href="http://www.sonatype.com/books/maven-book/reference/writing-plugins-sect-custom-plugin.html">plugin API</a>.  Granted, this isn&#8217;t complex like J2EE is complex, but for <b>scripting a build</b>, it&#8217;s rather ludicrous.</p>
<h4>Maven is hard to understand</h4>
<p>
I would be willing to bet that every one of my gripes is addressed through some crazy incantation.  But that&#8217;s not good enough.  The combined experience of the 7 developers at my company is about 70 years and not <b>one</b> of us can explain maven&#8217;s phases, identify the available targets, or successfully add new functionality for a pom without at least an hour on the net and maven&#8217;s documentation.</p>
<p> A great example is the release plugin.  All five developers here that have used it go through the same cycle of having no idea what it&#8217;s doing,  having it fail with a baffling error message, starting over and finally figuring out the one environment tweak that makes it work.  At the end of this journey each one (myself included) has realized all this is a HUGE wrapper around <tt>scp</tt> and a few <tt>svn</tt> commands. Running two commands to do a source code tag and artifact copy shouldn&#8217;t be this difficult.
</p>
<h4>Maven&#8217;s command line output is a straight-up lie</h4>
<p><pre>
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Compilation failure
</pre>
<p>&#8220;Compilation failure&#8221;, but it&#8217;s own definition is a failure and therefore an error (not an informational message).  Further, most build failures do not exit with nonzero.  This makes maven <b>completely unscriptable</b>.
</p>
<h4>Maven doesn&#8217;t solve the problems of make</h4>
<p>
Ant&#8217;s whole reason for being is &#8220;tabs are evil&#8221;, and that tells you something.  While maven&#8217;s description of itself is <a href="https://twitter.com/davetron5000/status/1656171374">a complete fabrication</a>, it at least has its heart in the right place.  However, it STILL fails to solve make&#8217;s shortcomings wrt to java:</p>
<ul>
<li>Maven doesn&#8217;t recompile the java classes that are truly out-of-date</li>
<li>Maven recompiles  java classes that are <b>not</b> out-of-date</li>
<li>Maven doesn&#8217;t allow for sophisiticated behavior through scripting</li>
<li>Maven replaces arcane magic symbols with arcane magic nested XML (e.g. pom files aren&#8217;t more readable than a Makefile)</li>
</ul>
<h4>Maven is slow</h4>
<p>My test/debug cycle is around a minute.  It should be 5 seconds (and it shouldn&#8217;t require an IDE).</p>
<h4>Conclusion</h4>
<p>
Apache&#8217;s Ivy + Ant is probably a better environment than maven for getting things done; a bit of up-front work is required, but it&#8217;s not an ongoing cost, and maintenance is much simpler and more straightforward.  Tools like <a href="http://buildr.apache.org/">Buildr</a> and <a href="http://raven.rubyforge.org/">Raven</a> seem promising, but it might be like discussing the best braking system for a horse-drawn carriage; utterly futile and irrelevant.</p>
<img src="http://feeds.feedburner.com/~r/daveblog5000/~4/Ix2CJV6zkpU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.naildrivin5.com/daveblog5000/?feed=rss2&amp;p=111</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://www.naildrivin5.com/daveblog5000/?p=111</feedburner:origLink></item>
		<item>
		<title>Git Workflow with SVN</title>
		<link>http://feedproxy.google.com/~r/daveblog5000/~3/BDfd8Cx7Jfg/</link>
		<comments>http://www.naildrivin5.com/daveblog5000/?p=102#comments</comments>
		<pubDate>Tue, 28 Apr 2009 19:50:23 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[version control]]></category>

		<guid isPermaLink="false">http://www.naildrivin5.com/daveblog5000/?p=102</guid>
		<description><![CDATA[The best way to get started with Git and have a better experience at work if you have to use SVN is to use git svn as a client to Subversion.  You can take advantage of Git&#8217;s awesomeness while not requiring your team or infrastructure to change immediately.

Setup
git svn clone -t tags -T trunk [...]]]></description>
			<content:encoded><![CDATA[<p>The best way to get started with Git <b>and</b> have a better experience at work if you have to use SVN is to use <tt>git svn</tt> as a client to Subversion.  You can take advantage of <a href="http://whygitisbetterthanx.com/">Git&#8217;s awesomeness</a> while not requiring your team or infrastructure to change immediately.
</p>
<h3>Setup</h3>
<p><tt>git svn clone -t tags -T trunk -b branches svn+ssh://your.svn.com/path/to/svn/root</tt><br />
(This may take a while for a large or old svn repo)</p>
<h3>Working on Trunk</h3>
<p>The initial clone should leave you on git&#8217;s <tt>master</tt> branch, which is connected to svn&#8217;s trunk.</p>
<ol>
<li><tt>git svn rebase</tt> <i># Optional: only if you want to get work from svn; you don&#8217;t have to</i></li>
<li>Hack some code</li>
<li><tt>git add any new files you created.txt</tt></li>
<li><tt>git commit -a</tt></li>
<li>Repeat from step 2 until done</li>
</ol>
<h3>Sharing Your Changes</h3>
<p>You will rebase your changes against&#8217;s SVN&#8217;s (this means git will pretend you made all your changes from SVN&#8217;s current HEAD, not the HEAD you started with [you do this to avoid conflicts and merges, which SVN cannot handle]).</p>
<ol>
<li><tt>git svn rebase</tt></li>
<li><tt>git svn dcommit</tt></li>
</ol>
<h4>If you got Conflicts</h4>
<ol>
<li>Git will tell you about them, so go and resolve them</li>
<li>For each file you had to resolve, <tt>git add the_filename</tt>
<li><tt>git rebase --continue</tt></li>
<li>Repeat until done</li>
</ol>
<h3>Working with SVN&#8217;s branches</h3>
<p>Suppose you need to do some work on a branch called <tt>1.3.x</tt> in your SVN repo:</p>
<ol>
<li><tt>git svn fetch</tt> <i># This updates your local copy of remote branches</i></li>
<li><tt>git checkout 1.3.x</tt># This checks out a remote branch, which you shouldn&#8217;t work directly on</i></li>
<li><tt>git checkout -b 1.3.x-branch</tt> <i># This creates a local branch you can work on, based on the remote 1.3.x branch</i></li>
<li>Hack some code</li>
<li><tt>git add</tt> and <tt>git commit -a</tt> as needed</li>
<li>Follow same procedure as above for Sharing Your Changes.  Git will send your changes to the 1.3.x branch in SVN and not the trunk</li>
</ol>
<h3>Merging the Changes You Made</h3>
<p>Due to the way git interacts with SVN, you shouldn&#8217;t automatically just merge your branch work onto the trunk.  This may create strange histories in SVN.</p>
<h3>So What?</h3>
<p>So, this isn&#8217;t buying you much more than you get with SVN.  Yes, when you <tt>git checkout 1.3.x-branch</tt> it&#8217;s lightning fast, and you can work offline.  Here&#8217;s a few things that happen to me all the time that would be difficult or impossible to do without Git.</p>
<h4>Gotta Fix a Bug Real Quicklike</h4>
<p>You are in the middle of working on a new feature and you need to to push out a bugfix in production code.  Your in-development code can&#8217;t be checked into trunk:</p>
<ol>
<li><tt>git stash</tt></li>
<li><tt>git checkout production-branch-name</tt></li>
<li><tt>git checkout -b bugfix-xyz</tt></li>
<li>Fix bugs</li>
<li><tt>git commit -a</tt></li>
<li><tt>git svn dcommit</tt></li>
<li><tt>git checkout master</tt></li>
<li><tt>git stash apply</tt></li>
</ol>
<p>You are now back where you started, without a fake revision just to hold your code and you didn&#8217;t have to go checkout the branch elsewhere.</p>
<h4>Can&#8217;t commit to SVN due to a release</h4>
<p>Often, teams restrict commit access to SVN while a release is being prepared.  If the team is releasing version 1.5 and I&#8217;m working on 1.6 features, there can be some period of time where I&#8217;m not supposed to commit, because the 1.5 release is being prepared and under feature freeze.</p>
<ol>
<li><tt>git commit -a</tt></li>
<li>Continuing working</li>
</ol>
<p>When feature freeze is over, then I&#8217;ll <tt>git svn dcommit</tt> to send my changes to the SVN server</p>
<h4>Blocked on Feature X, Want to work on Feature Y</h4>
<p>This happens to me quite frequently:  I&#8217;m slated to work on a few features that aren&#8217;t interdependent.  I start hacking away on Feature X and hit a roadblock and can&#8217;t continue working.  I&#8217;ve got a half-implemented feature and I can&#8217;t make any forward motion until a meeting next week.  Feature Y, on the other hand, is ready to go.  This requires some planning ahead:</p>
<ol>
<li><tt>git checkout master</tt></li>
<li><tt>git checkout -b feature-X</tt></li>
<li>Work on Feature X</li>
<li><tt>git commit -a</tt> etc. as I work</li>
<li>Get blocked; meeting next week.  D&#8217;oh!</li>
<li><tt>git checkout master</tt></li>
<li><tt>git checkout -b feature-Y</tt></li>
<li>Work on Feature Y</li>
</ol>
<p>At this point, X and Y are on two local branches and I can switch back and forth as needed.  Don&#8217;t underestimate how powerful this is, especially when you have certain features that are priorities, but can become blocked frequently.  I can now easily put aside Feature Y once I have my meeting and start back up on Feature X.  When I&#8217;m done, I <tt>git merge</tt> everything back to master and <tt>dcommit</tt> to SVN.</p>
<h4>Type your log message, save it, realize you forgot to reference a bug ticket #</h4>
<p>You have a bug tracker set up that links tickets and revisions; all you have to do is put the ticket # in your log message.  It&#8217;s a nice feature, but I forget to do it frequently.  As long as you haven&#8217;t done <tt>git svn dcommit</tt>, you can fix this:</p>
<ol>
<li><tt>git commit --amend</tt></li>
</ol>
<p>Your editor will pop up and you can change the log message!  Awesome.</p>
<h3>Advanced Stuff</h3>
<p>Once you get used to this, you will feel more comfortable doing some more advanced things.  </p>
<h4>Topic Branches</h4>
<p>The most obviously beneficial was touched on above, but it boils down to: <b>make every new feature on its own branch</b>.  This means you <b>never work on master</b> and you <b>never work on an SVN branch</b>.  Those are only for assembling what you will send to SVN.  This gives incredible flexibility to work on code when its convenient and not worry about checking in bad things.  Git calls this <i>topic branches</i>.</p>
<h4>Save your Experiments</h4>
<p>If you do everything on a branch, you don&#8217;t have to delete your work, ever.  You can go back and revisit experiments, or work on low-priority features over a long period of time with all the advantages of version control, but without the baggage of remote branches you have to share with the world.</p>
<h4>Cherry Pick</h4>
<p>With Git, you typically commit frequently and you restrict the scope of each revision.  A commit in git is more like a checkpoint, and a push in  Git is more like a commit in SVN.  So, commit in git like crazy.  What this lets you do is move diffs around.  On several occasions, I&#8217;ve had some code on a branch that I needed to use, but didn&#8217;t want to pull in the entire branch.  <tt>git cherry-pick</tt> lets me do that.</p>
<h4>Mindlessly Backup Your Repo</h4>
<ol>
<li><tt>ssh your_user@some.other.box.com</tt></li>
<li><tt>mkdir awesome_project</tt></li>
<li><tt>cd awesome_project</tt></li>
<li><tt>git init</tt></li>
<li><tt>exit</tt></li>
<li><tt>git remote add other-box your_user@some.other.box.com:/home/chrisb/awesome_project</tt></li>
<li><tt>git push --all other-box</tt></li>
<li><tt>echo "git push --force --all other-box" > .git/hooks/post-commit &#038;&#038; chmod +x .git/hooks/post-commit</tt></li>
</ol>
<p>You now will back up your repository on every commit to the other box.  Or, use <a href="http://www.github.com">GitHub</a>!</p>
<img src="http://feeds.feedburner.com/~r/daveblog5000/~4/BDfd8Cx7Jfg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.naildrivin5.com/daveblog5000/?feed=rss2&amp;p=102</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.naildrivin5.com/daveblog5000/?p=102</feedburner:origLink></item>
		<item>
		<title>REST Compliance Officer</title>
		<link>http://feedproxy.google.com/~r/daveblog5000/~3/azjThpNnd4c/</link>
		<comments>http://www.naildrivin5.com/daveblog5000/?p=92#comments</comments>
		<pubDate>Tue, 17 Mar 2009 20:26:32 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[rest]]></category>

		<guid isPermaLink="false">http://www.naildrivin5.com/daveblog5000/?p=92</guid>
		<description><![CDATA[With regard to this blog on REST compliance

Me: The Gliffy API is RESTFul
REST Compliance Officer: Does a &#8220;PUT&#8221; update the data at the given URL?
Me: Yes.
RCO: Trick Question!  It&#8217;s &#8220;URI&#8221;.  Is the only way to create a new resource done with a &#8220;POST&#8221;?
Me: Yes.
RCO: Is there exactly one endpoint, from which any and [...]]]></description>
			<content:encoded><![CDATA[<p>With regard to <a href="http://www.jroller.com/Solomon/entry/the_road_to_real_rest">this blog on REST compliance</a></p>
<blockquote><p>
<b>Me:</b> The Gliffy API is RESTFul<br />
<b>REST Compliance Officer:</b> Does a &#8220;PUT&#8221; update the data at the given URL?<br />
<b>Me:</b> Yes.<br />
<b>RCO:</b> Trick Question!  It&#8217;s &#8220;URI&#8221;.  Is the only way to create a new resource done with a &#8220;POST&#8221;?<br />
<b>Me:</b> Yes.<br />
<b>RCO:</b> Is there exactly one endpoint, from which any and all resource locators are discoverable?<br />
<b>Me:</b> Um, no, that puts undue burden on the client libraries, and over-complicates what we were trying to accomp&#8230;.<br />
<b>RCO:</b> <i>YOU ARE NOT RESTFUL!  READ FIELDING&#8217;S DISSERTATION, THE HTTP SPEC AND IMPLEMENT AN RFC-COMPLIANT URI  PARSER IN THREE DIFFERENT LANGUAGES.  NEXT!</i>
</p></blockquote>
<p>
Thank GODS that REST doesn&#8217;t have a spec.  If it did, it would still be in development.
</p>
<hr />
<p>
P.S. If you are going to coin a term and you want to <a href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven">bitch about it being misused</a>, maybe calling it a &#8220;style&#8221; isn&#8217;t the best idea.</p>
<img src="http://feeds.feedburner.com/~r/daveblog5000/~4/azjThpNnd4c" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.naildrivin5.com/daveblog5000/?feed=rss2&amp;p=92</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.naildrivin5.com/daveblog5000/?p=92</feedburner:origLink></item>
	</channel>
</rss>
