<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Jeff's Musings</title>
	<atom:link href="http://blog.jeffshurts.com/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.jeffshurts.com</link>
	<description>Observations and accumulated wisdom</description>
	<lastBuildDate>Fri, 07 May 2010 19:34:47 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A little Groovy magic &#8211; Lists and Property Accessors</title>
		<link>http://blog.jeffshurts.com/archives/91</link>
		<comments>http://blog.jeffshurts.com/archives/91#comments</comments>
		<pubDate>Fri, 07 May 2010 19:34:47 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[collections]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[properties]]></category>
		<category><![CDATA[Redpoint]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/?p=91</guid>
		<description><![CDATA[<p>Dynamic languages like Groovy and Ruby are all about productivity.  Not only do they eliminate the need to write tons of boilerplate code, they also contain all sorts of &#8220;syntactic sugar&#8221; &#8211; language features that let you accomplish a tremendous amount of work with very little code.</p>
<p>Most of these features &#8211; closures, ultra-convenient collection-oriented operators like the spread-dot (*.), etc., are well-documented.  Some, however, are a bit more arcane, and not realizing they exist can actually cost you a lot of time if you stumble into them inadvertently.</p>
<p>The feature I have in mind at the moment is a very convenient but somewhat surprising bit of collection behavior in Groovy.  I&#8217;ve been working with the language for quite a while, and have dutifully pored over books and language reference documents to become familiar with all of the groovy goodness at my disposal, but somehow I missed this one until someone on my project team found it &#8211; quite by accident.</p>
<p>Here&#8217;s the magic find.  In Groovy, if you have a list of objects, you can access, <em>on the list itself</em>, properties that belong to objects within the list.  The result, somewhat intuitively (but somehow quizzical at the same time), is a list of values of that property across all the members in the list.  Here&#8217;s an example to illustrate what I mean &#8211; just copy this and run it as a Groovy script.</p>
<pre class="brush: groovy;">
class Player {
def name
def teams

public String toString() {
&quot;${name} - played for ${teams}&quot;
}
}

def players =
[
new Player(name: &quot;Greg Maddux&quot;, teams: [&quot;Cubs&quot;, &quot;Braves&quot;]),
new Player(name: &quot;Ron Santo&quot;, teams: [&quot;Cubs&quot;, &quot;White Sox&quot;]),
new Player(name: &quot;Billy Williams&quot;, teams: [&quot;Cubs&quot;, &quot;Athletics&quot;]),
new Player(name: &quot;Bruce Sutter&quot;, teams: [&quot;Cubs&quot;, &quot;Cardinals&quot;]),
new Player(name: &quot;Lou Brock&quot;, teams: [&quot;Cubs&quot;, &quot;Cardinals&quot;]),
new Player(name: &quot;Gary Gaetti&quot;, teams: [&quot;Twins&quot;, &quot;Cubs&quot;]),
new Player(name: &quot;Ron Cey&quot;, teams: [&quot;Dodgers&quot;, &quot;Cubs&quot;]),
new Player(name: &quot;Ryne Sandberg&quot;, teams: [&quot;Cubs&quot;]),
new Player(name: &quot;Mark Grace&quot;, teams: [&quot;Cubs&quot;, &quot;Diamondbacks&quot;]),
new Player(name: &quot;Goose Gossage&quot;, teams: [&quot;Athletics&quot;, &quot;Yankees&quot;, &quot;Cubs&quot;]),
new Player(name: &quot;Sammy Sosa&quot;, teams: [&quot;Rangers&quot;, &quot;White Sox&quot;, &quot;Cubs&quot;]),
new Player(name: &quot;Larry Bowa&quot;, teams: [&quot;Phillies&quot;, &quot;Cubs&quot;]),
new Player(name: &quot;Rick Monday&quot;, teams: [&quot;Dodgers&quot;, &quot;Cubs&quot;]),
new Player(name: &quot;Dave Kingman&quot;, teams: [&quot;Rangers&quot;, &quot;Mets&quot;, &quot;Cubs&quot;]),
new Player(name: &quot;Joe Girardi&quot;, teams: [&quot;Cubs&quot;, &quot;Cardinals&quot;, &quot;Yankees&quot;])
]

def playerNames = players.name
println &quot;Here, amazingly enough, is a list containing the names of all those players:\n $(playerNames)&quot;
</pre>
<p>Once you know this behavior exists, it&#8217;s pretty easy to find situations where it&#8217;s an insanely convenient feature.  If you don&#8217;t know it exists, you can get some pretty confusing results.  In our case, we were running a GORM query to retrieve a domain object using an alternate ID (expecting a single result), and incorrectly used the <code>list()</code> method (we should have used <code>get()</code>, which returns the domain object, whereas <code>list()</code> always returns a list).</p>
<p>In our code, after querying for the domain object, we accessed properties of the object, and were puzzled when instead of getting Strings and Integers and Dates, we were getting single-member <em>lists</em> of Strings and Integers and Dates.  Each list <code>contained</code> the value we expected, inexplicably embedded in a List instance.  It took a little head-scratching before we figured out that the root cause was that our query was returning a list containing our domain object, and our code that accessed the properties, which would have failed miserably in Java if attempting to treat a List as though it were a domain object, was happily drilling through the wall of that list and getting at its contents.</p>
<p>Syntactic sugar?  Definitely.  Violation of the principle of least surprise?  Maybe.  Will I use it, now that I know it&#8217;s a tool at my disposal?  Absolutely.</p>
<p>Stay Groovy, my friends&#8230;</p>
]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/archives/91/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Grails Pagination and CriteriaBuilder</title>
		<link>http://blog.jeffshurts.com/archives/74</link>
		<comments>http://blog.jeffshurts.com/archives/74#comments</comments>
		<pubDate>Thu, 29 Apr 2010 19:27:42 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Groovy/Grails]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[Redpoint]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/?p=74</guid>
		<description><![CDATA[A colleague of mine and I have agreed on an analogy for Grails development:  it’s like driving on the Autobahn, with serious sets of speed bumps every few miles.  One minute you’re flying along in hyper-productivity mode, and the next you’re inching along - digging through reference docs and forums trying to figure out why some little feature isn’t working.

My most recent speed bump is one that’s likely to appear in front of just about every Grails developer - getting pagination working with a result set generated by CriteriaBuilder - so I figured I’d help everyone join me in putting it in the rearview mirror.]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/archives/74/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using Grails Controller Interceptors To Avoid Rampant Testing</title>
		<link>http://blog.jeffshurts.com/archives/65</link>
		<comments>http://blog.jeffshurts.com/archives/65#comments</comments>
		<pubDate>Mon, 12 Apr 2010 14:33:57 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Groovy/Grails]]></category>
		<category><![CDATA[Agile]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[Redpoint]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/?p=65</guid>
		<description><![CDATA[<p>Test-driven development and the resulting test coverage it affords are some of the most important benefits of modern development practices.  When it comes time to refactor code or make a significant functional change, there’s nothing like the peace of mind afforded by a comprehensive set of well-written unit tests all emitting that wonderful emerald green.</p>
<p>But such peace of mind comes at a cost.  I’ve heard estimates from various teams I’ve talked to stating that the cost of writing unit tests for adequate code coverage (usually 50% to 80% on Java projects) can range from equivalent to the production code itself, to five times that.  The problem with these estimates, of course, is subjectivity.  For example, if you have found a bug using a test and work to fix the test, are you mentally counting that time as test-writing or code-writing?</p>
<p>Estimating factors aside, the plain fact is that testing does amplify the cost of software development – at least in the short term.  Which means that a software engineer who really cares about his customer’s bottom line should always be on the lookout for ways to avoid the increased cost of testing.</p>
<p>This line of thinking arose the other day on the project I’m currently working on.  It’s a Groovy/Grails web application with some public, customer-facing components and some internal-use components.  We’re using Grails scaffolding as much as is practical for the relatively infrequently-used internal-use features to save time and money.  In most cases, we have generated and tweaked the UI components (GSP pages) to smooth over some of the uglier bits of scaffolded pages, but we have tried not to generate any of the controller code, instead relying on Grails’ generate-at-runtime approach by including <code>def scaffold = true</code> in these controllers.</p>
<p>Why not generate the source?  Because generated code is deceptively expensive!  The minute a feature springs into  existence in your code base, it needs to be tested – even if that code was generated by a framework like Grails.  And Grails controller closures – <code>insert</code> and <code>update</code>, as the case in point here, do a significant amount work for you.  Data binding.  Optimistic locking exception handling.  Routing of validation errors.  All things that “just work” in scaffolded code, but which might be broken by someone once the code actually becomes part of your code base.</p>
<p>So when the need arose to customize part of the logic in insert and update closures (to do some custom interpretation of a series of check boxes on a form that couldn’t be made to conform to the default binding mechanism), we began looking for ways to override binding logic without generating and modifying the closures themselves.</p>
<p>As usual, Grails has a solution at the ready – controller <a href="http://www.grails.org/Controllers+-+Interceptors">interceptors</a>.  All we had to do was declare an interceptor that fires before insert and update closures, and in that closure, inspect our list of check boxes and set a <code>params</code> value that would then be assigned to our domain object through the normal binding process.</p>
<p>By using an interceptor, we completely avoided the need to generate (and assume custodianship of) the <code>insert</code> and <code>update</code> closures in this controller – which means we didn’t have to spend valuable time writing unit tests to cover these Grails-supplied features that could be broken once the code actually exists. </p>
<p>I guess I can summarize this little victory this way:  Having tested code for an application feature is far better than having untested code.  Having no code at all is better than either.  </p>
<p>Stay Groovy, my friends.</p>
]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/archives/65/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>All-Time Favorite Instrumental Tracks</title>
		<link>http://blog.jeffshurts.com/archives/57</link>
		<comments>http://blog.jeffshurts.com/archives/57#comments</comments>
		<pubDate>Thu, 11 Mar 2010 15:12:36 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[acoustic]]></category>
		<category><![CDATA[best of]]></category>
		<category><![CDATA[instrumental]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/?p=57</guid>
		<description><![CDATA[I’ve been meaning to put together a list of my favorite all-instrumental recordings for some time now, and finally found some time to get it done.  I’ve heard a lot of acoustic music over the years, and the list below represents my personal highlight reel.]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/archives/57/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Elegant Design, Customer Service:  It&#8217;s In the Details</title>
		<link>http://blog.jeffshurts.com/archives/51</link>
		<comments>http://blog.jeffshurts.com/archives/51#comments</comments>
		<pubDate>Tue, 02 Feb 2010 15:00:40 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Customer Service]]></category>
		<category><![CDATA[Redpoint]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/archives/51</guid>
		<description><![CDATA[<p>I recently purchased an Apple bluetooth keyboard and Magic Mouse for my Mac Mini (which I bought with the intention of using as a home theater media hub, but which gets almost as much use for &#8216;normal&#8217; computer tasks).</p>
<p>When I first started test driving the Magic Mouse, I happened to be in iTunes, and happened to need to adjust the volume &#8211; which is a horizontal slider in the UI.  I thought to myself, &#8220;This mouse has the ability to do scrolling in any direction &#8211; I wonder what happens if I hover over the volume control and swipe right?&#8221;  Bam.  Of course it worked.  It&#8217;s Apple, and they think of *everything.*</p>
<p>I was truly impressed.  And, being an engineer and naturally inquisitive, I took notice that I was impressed &#8211; particularly by such a &#8220;little thing.&#8221;  I then realized that I was impressed not <em>despite</em> the fact that this was a little thing, but <em>because</em> it was a little thing.  The sort of thing that other user interface and hardware designers might well have missed.</p>
<p>Which brings me to the moral of this story.  I work in a consulting firm, and our goal is not merely to meet our customers&#8217; expectations, but to surpass them.  In short, to <em>impress</em> them.  I think that sometimes we find this hard to do.  We need to remind ourselves that sometimes it&#8217;s just the little things we do &#8211; things that others might have missed &#8211; that will make the biggest impression.</p>
]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/archives/51/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I&#8217;ve looked at clouds from both sides now&#8230;</title>
		<link>http://blog.jeffshurts.com/archives/45</link>
		<comments>http://blog.jeffshurts.com/archives/45#comments</comments>
		<pubDate>Wed, 08 Jul 2009 03:23:42 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Redpoint]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/?p=45</guid>
		<description><![CDATA[<p>I stumbled across a very cool cloud-based music service called <a title="SoundCloud" href="http://www.soundcloud.com" target="_blank">SoundCloud</a> (http://www.soundcloud.com) today.  I love it for two very different reasons.  First, it&#8217;s a great (maybe even killer) application of cloud computing technology, taking advantage of the Great Server Farm In the Sky to solve a real problem.  Second, I love the solution itself.</p>
<p>See, technology is my day job.  When I&#8217;m not working (or walking the dog, or schlepping kids around town), I usually have some sort of musical instrument in my hands. or in front of me. Guitar, mandolin, bass, keyboards, drums and trumpet, for now.  Hope to add to the collection soon &#8211; I think I need a bouzouki.  Or maybe a dobro.  But I digress&#8230;</p>
<p>When I have a block of free time and a little peace and quite in the house, I like to break out my recording gear and see what I can throw together.  And, occasionally, share it with a few friends to see what they think.  Or even send a track to a friend who&#8217;s a <em>real</em> drummer to lay down a drum track for me to mix in later.</p>
<p>In the past, sharing music online has been inconvenient at best.  Oh, there are music sharing sites like <a title="SoundClick" href="http://www.soundclick.com" target="_blank">SoundClick</a>, or social sites like <a title="MySpace" href="http://www.myspace.com" target="_blank">MySpace</a> that cater to musicians.  But they all have some pretty serious limitations (like having to actually log into their service to find and listen to tracks).</p>
<p>SoundCloud is different.  It&#8217;s a <strong>seriously </strong>open, cloud-based music storage and publishing service.  I just signed up an hour ago, and within minutes I was uploading my first track.  (I love, by the way, that you specify the file to upload first, and it <em>automatically </em>starts uploading while you fill in the track info form.)</p>
<p>But the really cool part is the openness of the service.  There&#8217;s no need for anyone to go to their site to hear my music.  I can email it to them, or drop a widget into Facebook or a blog entry (as I&#8217;ve done here), and voila.  Music.  Where I want it.  No strings attached.</p>
<p>And now, if you&#8217;ll excuse me, I have a recording project to dive into&#8230;</p>
<div style="font-size: 11px;"><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="100%" height="81" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowscriptaccess" value="always" /><param name="src" value="http://player.soundcloud.com/player.swf?track=illinois-river-rag&amp;show_comments=true&amp;auto_play=false&amp;color=aa2f3b" /><embed type="application/x-shockwave-flash" width="100%" height="81" src="http://player.soundcloud.com/player.swf?track=illinois-river-rag&amp;show_comments=true&amp;auto_play=false&amp;color=aa2f3b" allowscriptaccess="always"></embed></object></p>
<div style="padding-top: 5px;"><a href="http://soundcloud.com/jeffshurts/illinois-river-rag">Illinois River Rag</a> by  <a href="http://soundcloud.com/jeffshurts">JeffShurts</a></div>
</div>
]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/archives/45/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>On Shimmer and Patience</title>
		<link>http://blog.jeffshurts.com/archives/40</link>
		<comments>http://blog.jeffshurts.com/archives/40#comments</comments>
		<pubDate>Mon, 13 Apr 2009 01:31:00 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Continuous Integration]]></category>
		<category><![CDATA[Redpoint]]></category>
		<category><![CDATA[Unit Testing]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/?p=40</guid>
		<description><![CDATA[<p><!--[endif]--></p>
<p class="MsoNormal">Remember <em>Shimmer</em> on Saturday Night Live?<span> </span>Dan Aykroyd and Gilda Radner?<span> </span>“It’s a dessert topping <em>and</em> a floor wax!”<span> </span>If you’re as old as I am or enough of an SNL fan to have caught that old episode on DVD, you’re probably chuckling a little.<span> </span>Humor has many triggers in the human brain, and absurdity is certainly one of them.</p>
<p class="MsoNormal">That’s why my initial reaction to something that happened at work the other day was to laugh – a reaction which, thankfully, I was successful in suppressing.<span> </span>Not only because laughing would<span> </span>have been unprofessional, but because, as is often the case, my first impression was superficial and, ultimately, off the mark.</p>
<p class="MsoNormal">The topic of discussion was the Continuous Integration build at a client.<span> </span>Let’s see if I can recreate the scene.<span> </span>Names, of course, have been changed to protect those who may not want their names to appear here…</p>
<p class="MsoNormal"><strong>Jeff the Consultant:</strong><span> </span>I see that there are 800-odd unit tests in our code base, and I can run them locally, but the CI build only runs 150 or so of them.<span> </span>Is something wrong?</p>
<p class="MsoNormal"><strong>Bob the Builder:<span> </span></strong>No, this is correct.</p>
<p class="MsoNormal"><strong>Jeff the Consultant:</strong><span> </span>Come again?</p>
<p class="MsoNormal"><strong>Bob the Builder:<span> </span></strong>Yes, we do this intentionally.</p>
<p class="MsoNormal"><strong>Jeff the Consultant:</strong><span> </span>Okay, I have to ask.<span> </span>Why?<span> </span>Does it take too long to run all of the tests?</p>
<p class="MsoNormal"><strong>Bob the Builder:<span> </span></strong>No, not really.<span> </span>The build with all the tests runs in 10 minutes or so.</p>
<p class="MsoNormal"><strong>Jeff the Consultant:</strong><span> </span>Then why do we run a just a subset of them on code checkin?</p>
<p class="MsoNormal"><strong>Bob the Builder:<span> </span></strong>Well, we run the full set of tests in a different build that runs nightly.</p>
<p class="MsoNormal"><strong>Jeff the Consultant:</strong><span> </span>Hmm&#8230;<span> </span>Doesn’t running the tests at night make it difficult to track down whose code submission is responsible for tests that start failing?<span> </span>And doesn’t it remove the benefit of immediate feedback?<span> </span>I’m getting on in years, and sometimes I get to work in the morning not remembering a lot about what I did the night before.</p>
<p class="MsoNormal"><strong>Bob the Builder:<span> </span></strong>I see your point.<span> </span>It would be a lot better if we ran the full set of tests all the time, on every code check-in.</p>
<p class="MsoNormal"><strong>Jeff the Consultant:</strong><span> </span>Great.<span> </span>So you’ll make the necessary changes to the build script?</p>
<p class="MsoNormal"><strong>Bob the Builder: </strong><span> </span>No, I can’t do that.</p>
<p class="MsoNormal"><strong>Jeff the Consultant:</strong><span> </span>Wonderful, thanks… wait – did you just say “No?”</p>
<p class="MsoNormal"><strong>Bob the Builder: </strong><span> </span>Correct.<span> </span>I can’t change the build.</p>
<p class="MsoNormal"><strong>Jeff the Consultant:</strong><span> </span>Okay, I have to ask.<span> </span>Why not?</p>
<p class="MsoNormal"><strong>Bob the Builder: </strong><span> </span>Because we don’t want this build to fail.</p>
<p class="MsoNormal"><strong>Jeff the Consultant:</strong><span> </span><em>(This is about the point where I had to start physically suppressing laughter)</em><span> </span>But the build is <em>supposed</em> to fail if there are broken tests.<span> </span>That’s how we know there’s something that needs to be fixed, and who’s responsible – er, best qualified to fix it.</p>
<p class="MsoNormal"><strong>Bob the Builder: </strong><span> </span>Right, I understand that.<span> </span>But the jars we produce in this build get deployed in an overnight process.<span> </span>So we don’t want the build to fail, because if it does, the daily build won’t get deployed.</p>
<p class="MsoNormal"><strong>Jeff the Consultant:</strong><span> </span>Okay, I see that.<span> </span>But why do you <em>want</em> to deploy a build that you know has bugs in it?<span> </span>Or, in this case, that <em>might</em> have bugs in it, since you’re not running all of the tests…</p>
<p class="MsoNormal"><strong>Bob the Builder: </strong><span> </span>Well, the deployment isn’t just for this team.<span> </span>There’s another team on the East Coast that needs that build to be deployed every day.</p>
<p class="MsoNormal"><strong>Jeff the Consultant:</strong><span> </span>Hmm… interesting.<span> </span>Are the tests we’re not running <em>our</em> tests or <em>theirs</em>?</p>
<p class="MsoNormal"><strong>Bob the Builder: </strong><span> </span>Mostly ours, I think.<span> </span>But it doesn’t matter – we can’t let broken tests stop the deployment, because usually only a small number of features are affected by those tests, and lots of people need to see the deployed application the next day in our demo environment.</p>
<p class="MsoNormal"><strong>Jeff the Consultant:</strong><span> </span>Okay, that makes sense – I guess.<span> </span>But isn’t there another way to do this?<span> </span>For example, couldn’t we run the full suite of unit tests at code check-in time, and make the <em>nightly</em> build the one that skips tests and reliably produces the demo jar files?<span> </span>That way at least we’d get back the benefit of immediate feedback and have a better idea whose code is causing a test to start failing.</p>
<p class="MsoNormal"><strong>Bob the Builder: </strong><span> </span>I think we could do that.<span> </span>But I don’t have time to dig into an overhaul of the build process, because I have development responsibilities too, and we’re only 2 days from code freeze.</p>
<p class="MsoNormal"><em>(Exit cubicle, stage right…)</em></p>
<p class="MsoNormal">By this time my head was spinning.<span> </span>I wasn’t sure whether what I’d just heard made sense, or whether I’d just been had.<span> </span>I was pretty sure the whole build arrangement they had settled on was crazy, but I could also see how an organization could have evolved into this arrangement because of conflicting needs.</p>
<p class="MsoNormal">The root of their problem is the Shimmer conundrum.<span> </span>It’s neither a dessert topping nor a floor wax, but their CI build is certainly trying to be two very different things at the same time.<span> </span>It was probably started as a CI build in the Agile sense, with the primary purpose being immediate feedback in the form of unit test results.<span> </span></p>
<p class="MsoNormal">But of course, like any build, it also <em>builds something.</em><span> </span>Those jar files were ripe for the picking, and some enterprising person had the great idea to deploy them every day so interested parties in the company would be able to see the application “fresh from the oven” – with all of the evolving new features on display.</p>
<p class="MsoNormal">The problem is that the secondary purpose of this particular build – generation of compiled, deployable software, became more critical to <em>somebody</em> – some person with influence – and the build began to slowly stop meeting its initial purpose.</p>
<p class="MsoNormal">So, is there a point to this rambling blog post?<span> </span>Indeed there is.<span> </span>It’s a word of caution to those of us in the consulting profession.<span> </span>It’s very easy for those of us who spend a lot of time reading and in other ways learning about “ideal” situations – such as well-run Agile projects – to become easily frustrated when we encounter things that are in some way less than ideal.<span> </span>We have to remember to suspend judgment long enough to understand the big picture – all of the various problems our clients are trying to juggle – and then offer our assistance in helping improve things, at a pace that makes sense in their environment.</p>
<p class="MsoNormal">I’ll try to remember this myself as I return to work tomorrow…</p>
]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/archives/40/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Of Entities and Identities</title>
		<link>http://blog.jeffshurts.com/archives/32</link>
		<comments>http://blog.jeffshurts.com/archives/32#comments</comments>
		<pubDate>Sat, 21 Feb 2009 15:18:30 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Redpoint]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/?p=32</guid>
		<description><![CDATA[<p>I really like Hibernate.  Sure, it can be frustrating at times, the learning curve can be steep, and some of the exceptions you get when you do stupid things aren&#8217;t all that helpful.  But the fact that it&#8217;s frustrating and hard to learn are manifestations of the fact that it&#8217;s tackling some really thorny problems.  And the cryptic-exception issue does get a little better with each release.</p>
<p>There is one thing, however, that has bothered me since I started using Hibernate several years ago.  A deep bother.  Not a &#8220;this is a nuisance, but I can live with it&#8221; bother, but more of a &#8220;this is so fundamental an issue that there just <em><strong>has </strong></em>to be a better solution to it than is being offered by Hibernate&#8217;s authors&#8221; bother.</p>
<p>The problem:  bridging the gap between object identity and database identity.  In most modern database schemas, tables are defined with a numeric primary key column, which is populated through some unique key assignment mechanism (Identity columns in SQL Server or MySQL, sequences in Oracle, etc).</p>
<p>This works great at the database layer.  But problems arise in the JVM (or CLR for you NHibernate folks).  In order for objects representing database entities (those managed by Hibernate) to be handled properly in collections (including Hibernate cache), objects that have the same database identity need to be recognized as equals as well.  In Java, this means overriding equals() and hashCode() such that any two objects that represent the same database entity will be equal, and return the same hash code.</p>
<p>The &#8220;obvious&#8221; solution, at first blush, would be to base <strong>equals() </strong>and <strong>hashCode()</strong> on entity ID values.  This works great for entities <em>created </em>by Hibernate, which represent existing rows in a database, all with unique ID&#8217;s.  The problem has to do with <em>new</em> entites that you create programmatically, which haven&#8217;t yet been saved.  Those entities will typically have a <em>null</em> ID value &#8211; and if you base equality on ID values, any two unsaved instances will be considered equal.</p>
<p>There are actually two problems when dealing with unsaved entity objects.  The first, as stated above, is that they don&#8217;t yet have a unique identity &#8211; so multiple new instances will collide in collections like Maps and Sets.  The other problem is that the identity of these objects <em>will be set at some point</em>, which violates part of the contract of <strong>hashCode()</strong> &#8211; the part that says its value must not mutate over time.</p>
<p>To avoid all of thes problems, Hibernate&#8217;s authors have long recommended a workaround &#8211; use &#8220;natural keys&#8221; instead of identity values for<strong> equals() </strong>and <strong>hashCode(). </strong>The problem with this is that many entities simply don&#8217;t have a natural key &#8211; that is, a set of one or more attributes whose values uniquely identify the entity.  And those that do often fail the hashCode() qualification that the value should not change over time.</p>
<p>There are other possible solutions I&#8217;ve seen or come up with myself, but all had at least one glaring weakness.  It seemed that there was no silver bullet for dealing with database-generated identity values in Hibernate.</p>
<p>And therein lies the silver bullet.  Don&#8217;t use the database (or Hibernate) to generate identity values.</p>
<p>I stumbled across a wonderful article on O&#8217;Reilly&#8217;s OnJava site that quite clearly describes this problem (in more detail than I do here), and offers what I believe to be the only real solution.  Check it out at <a title="http://www.onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html" href="http://www.onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html" target="_blank">http://www.onjava.com/pub/a/onjava/2006/09/13/dont-let-hibernate-steal-your-identity.html</a>.</p>
<p>And now, as I look out the window at the late February snowstorm, I think maybe it&#8217;s time for <strong>me</strong> to hibernate&#8230;</p>
]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/archives/32/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Those folks at Adobe put on a good show&#8230;</title>
		<link>http://blog.jeffshurts.com/archives/30</link>
		<comments>http://blog.jeffshurts.com/archives/30#comments</comments>
		<pubDate>Fri, 28 Nov 2008 02:50:45 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Redpoint]]></category>
		<category><![CDATA[RIA]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/?p=30</guid>
		<description><![CDATA[<p>Last week I attended the Adobe Max conference in San Francisco.  It was my first time at this particular conference, and I must say I was impressed.  The keynote speakers were engaging, the forthcoming product suite (Creative Suite 4, CS4 for short) was compelling, and most of the sessions and labs I attended were well worth making the trip from Chicago.</p>
<p>Now that I&#8217;ve had a week to let all the new information bounce around in my head for a while and settle into semi-organized piles of data, I have two major takeaways from the conference.</p>
<p>Firstly, Adobe users <em>love</em> their products, and they&#8217;re tremendously enthusiastic about the direction Adobe is taking them.  In the main sessions, where all 6,000+ attendees were in the same huge room, many new features were met with thunderous applause.  You just don&#8217;t get that sort of thing at a WebSphere conference.</p>
<p>Secondly, if CS4 is a big success &#8211; and I have no doubt but that it will be &#8211; we&#8217;ll start to see changes in the relationship between designers and developers on teams building RIA&#8217;s.  CS4 contains a brilliant piece of software, Flex Catalyst, that lets designers using PhotoShop and Flash save content to the same source files as developers using Flex Builder.  This provides a seamless transition from initial UI mockup to prototype to working application &#8211; and keeps the UI in the hands of the designer a little longer than has traditionally been the case.  Designers can now exert great control over not only over the way an applicaiton <em>looks</em>, but also over the way it <em>behaves</em> as a user interacts with the various widgets in the UI.  This will bring new challenges to RIA developers who work on teams with designers &#8211; developers will have less control, less latitude to say &#8220;We can&#8217;t do that &#8211; it&#8217;ll take too long&#8221;, or &#8220;Sorry, the tool won&#8217;t let us do that.&#8221;  Developers will inherit a prototype that is quite complete in terms of look <em>and feel</em>, and will be focused more on adding functional meat to the UI bones (filling lists with live data, wiring events to real business services, etc.).</p>
<p>Oh, I did forget to mention one thing.  This was my first time in San Francisco.  What a wonderful city!  I&#8217;ll definitely be back&#8230;</p>
]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/archives/30/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Practical Look at the Semantic Web</title>
		<link>http://blog.jeffshurts.com/archives/19</link>
		<comments>http://blog.jeffshurts.com/archives/19#comments</comments>
		<pubDate>Thu, 13 Nov 2008 02:42:43 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Redpoint]]></category>
		<category><![CDATA[Semantic Web]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/?p=19</guid>
		<description><![CDATA[<p>The faint murmurs I&#8217;ve been hearing related to the Semantic Web are becoming louder.  Is it the Next Big Web Thing?  Or just another vision that will never be fully realized &#8211; another solution looking desperately for a problem?</p>
<p>I must admit I&#8217;ve been a bit puzzled by the hype &#8211; but then I&#8217;ve never been one to jump on a bandwagon until I know just where it&#8217;s headed.  So I started to dig a little deeper into this one, and I&#8217;m starting to see how it will be useful.  I won&#8217;t prognosticate here as to how soon.  Rather, I&#8217;ll spend a little time explaining what it is and what &#8220;problem&#8221; it solves, and let you do your own crystal-ball-gazing.</p>
<p>Before I start, a bit about my background.  I&#8217;m an old-school computer guy.  Learned BASIC on a Commodore VIC-20.  One of my college profs had kids (nick)named COBOL and FORTRAN.  I knew databases before they were relational, and languages before they were object-oriented.  So I&#8217;ve seen a few major technology shifts (mainframes to PC&#8217;s to networked PC&#8217;s to the Internet, flat files to B-trees to relational databases to OODB&#8217;s, etc.).</p>
<p>I don&#8217;t expect the Semantic Web to be as game-changing as any of these.  But I do think it&#8217;ll be useful and catch fire at some point &#8211; and will be of benefit to both consumers of technology and companies that make money through innovative use of technology.</p>
<h1>The Semantic Web &#8211; What Is It?</h1>
<p>I like to explain things through analogy.  If I miss your frame of reference here, sorry &#8211; I tried.  Remember the good old days when lots of data sat around in &#8220;flat files?&#8221;  Maybe they were &#8220;positional&#8221; in nature, with the first 10 characters representing a social security number, the next 20 a first name, the next 20 a last name, etc.  Or maybe they were delimited, with commas, tabs or other characters separating fields.  At any rate, they all had one thing in common &#8211; a person (let alone a computer program) couldn&#8217;t interpret them without the &#8220;magic key&#8221; &#8211; some form of metadata that explained how the contents were arranged.  For mainframe files, the &#8220;magic key&#8221; was often a COBOL file layout.  You get the idea.</p>
<p>Fast forward a few years to the advent of relational databases.  Suddenly, information was well-organized, and &#8211; here&#8217;s the kicker &#8211; <em>self-explanatory</em>.  Not only could you easily run a query and get rows of neatly organized data with explanatory headings, you could also query database metadata &#8211; the schema &#8211; to inquire about the contents of the database.</p>
<p>Okay.  Now, fast forward another decade and a half or so, to the dawn of the Web.  Suddenly we have <em>massive</em> amounts of information available for perusal, and it&#8217;s (usually) pretty understandable by human readers.  But don&#8217;t ask software to make heads or tails of an HTML document.  A web page might contain information about an individual &#8211; name, address, phone number, freckle count, favorite &#8217;80&#8217;s hair metal band, etc. &#8211; but that information isn&#8217;t organized in such a way that a software parser can pick it apart and know what it has (see below).</p>
<pre class="brush: xml;">
&lt;html&gt;
&lt;body&gt;
&lt;p&gt;My first name is Jeff.&lt;/p&gt;
&lt;p&gt;My last name is Shurts.&lt;/p&gt;
&lt;p&gt;My phone number is 555-1212.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Enter the Semantic Web.  If you were asked to write a piece of software that would dig through a file and display someone&#8217;s first name, last name and phone number, wouldn&#8217;t you be happier if that file&#8217;s content looked like this?</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot; ?&gt;
&lt;person&gt;
&lt;firstName&gt;Jeff&lt;/firstName&gt;
&lt;lastName&gt;Shurts&lt;/lastName&gt;
&lt;phoneNumber&gt;555-1212&lt;/phoneNumber&gt;
&lt;/person&gt;
</pre>
<p>Ah, much better.  Give me a DOM or SAX parser and I&#8217;m golden.  No ambiguity, no tricky parsing tricks.  But wait &#8211; XML has been around forever &#8211; that can&#8217;t be the essence of some Next Big Thing, right?</p>
<p>Right.  Plain old XML is great for use in applications where there are a limited number of interested parties, all of whom agree on the format (schema, or DTD) of the data being exchanged.  And XML has been used very effectively in this way &#8211; expecially in Web Services.</p>
<p>But back to our assignment from a few paragraphs ago.  What if we were given a trickier problem&#8230; say, to write a web crawler that would scan millions of web pages looking for information about people &#8211; specifically first and last names, and phone numbers.  We aren&#8217;t given a sample XML file or an XML schema.  We just know we want information about <em>people</em>.</p>
<p>Now we have a nightmare on our hands.  We might be able to look for XML documents (giving up on HTML altogether), and look for tags like <code>&lt;firstName&gt;Jeff&lt;/firstName&gt;</code>.  But we don&#8217;t have any guarantees that the tags were used in a manner consistent with their apparent meaning.  Wouldn&#8217;t it be great if there were a way that people could (and would) encode data such that it was very clear, in a globally-understood manner, what the data means?</p>
<p>Enter RDF (Resource Description Framework).  Based on XML, but forging on to solve bigger and more sophisticated problems, RDF provides a syntactic means of encoding very specific intent along with information.  Here is an example:</p>
<pre class="brush: xml;">
&lt;rdf:RDF xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;
xmlns:foaf=&quot;http://xmlns.com/0.1/foaf/&quot; &gt;
&lt;foaf:firstName&gt;Jeff&lt;/foaf:firstName&gt;
&lt;foaf:lastName&gt;Shurts&lt;/foaf:lastName&gt;
&lt;foaf:phone&gt;555-1212&lt;/foaf:phone&gt;
&lt;/rdf:RDF&gt;
</pre>
<p>This document not only teases out the interesting bits into discrete fields, but also <em>denotes that these fields are very specific attributes that are defined by a particular well-known model</em> (in this case, FOAF, or Friend of a Friend).  In a way, RDF does for web-hosted data what WSDL (Web Services Discovery Language) did for web-hosted services &#8211; it provides a well-understood description that can be programmatically interrogated and understood.</p>
<h1>Okay, I get it.  But how is this a game-changer?</h1>
<p>Well, so far, it&#8217;s not.  But it might be, and its chances are getting better.  Earlier this year, Yahoo announced plans to include Semantic Web features in its search engine, to provide richer, more intelligent searches, as well as enhanced output from search results.</p>
<p>For those of you who know SQL, wouldn&#8217;t it be pretty nice to be able to run the equivalent of this query &#8211; not against a local Oracle table, but against the Web?</p>
<pre class="brush: sql;">
SELECT firstName, lastName
from People
where lastName = 'Shurts'
and homeCity = 'Saint Charles'
</pre>
<p>Voila &#8211; the Web as a giant database!  Starting to see how this might be a game-changer?  Finding just the information you are looking for with today&#8217;s search engines is an art &#8211; you have to find just the right set of keywords, and then hope for the best.  In a semantically-rich future, you&#8217;ll be able to scour the web with the precision of a database query.</p>
<p>And, to quote the old Ronco commercials I used to watch when I wasn&#8217;t writing BASIC code on that VIC 20: &#8220;But wait, there&#8217;s more!&#8221;  Not only will information searches be more precise, the <em>results</em> of those searches will be presented in a richer, semantically meaningful way.  Instead of the ubiquitous three-liner (page title, URL, and a snippet) for each match, you will one day be presented information that makes sense given the context of your query.  You searched for people?  You get business-card-like search results.  You searched for CD&#8217;s?  You get track listings and cover art for each CD that matched your query (e.g. select * from albums where backgroundSinger includes &#8216;Michael McDonald&#8217;).</p>
<h1>In conclusion&#8230;</h1>
<p>Well, there it is.  That&#8217;s as much of the Semantic Web as I&#8217;ve been able to wrap my head around so far.  So what do you think?  Is it a game changer?  Or just incremental improvement over current Web technologies?  Will it take off, or are there barriers to adoption?  (If I&#8217;m an online merchandiser, do I really want to <em>help</em> web crawlers snarf my prices so they can include them in comparison-shopping sites?)  I&#8217;d love to hear from you!</p>
]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/archives/19/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
