<?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>Mon, 16 Apr 2012 16:39:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>DCI (Data-Context-Interaction) &#8211; what is it, and when should I use it?</title>
		<link>http://blog.jeffshurts.com/2012/04/10/138/</link>
		<comments>http://blog.jeffshurts.com/2012/04/10/138/#comments</comments>
		<pubDate>Tue, 10 Apr 2012 16:52:05 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Agile]]></category>
		<category><![CDATA[Professional]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Redpoint]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/?p=138</guid>
		<description><![CDATA[If you're a hardcore, 10-hours-a-day Rails developer, you already know about DCI.  For the rest of you, here's a gentle introduction.]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/2012/04/10/138/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Declining Role of the Design Pattern</title>
		<link>http://blog.jeffshurts.com/2012/04/04/java-to-ruby-or-learning-leading-to-unlearning/</link>
		<comments>http://blog.jeffshurts.com/2012/04/04/java-to-ruby-or-learning-leading-to-unlearning/#comments</comments>
		<pubDate>Wed, 04 Apr 2012 15:21:04 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Professional]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Redpoint]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/?p=132</guid>
		<description><![CDATA[<p>With the ascension over the last half-decade of Ruby into the upper echelon of programming languages for business applications, there has been ever-increasing demand for Ruby developers.  Which means there are a lot of folks who cut their OO teeth on languages like Java and C# who now find themselves swimming in Ruby&#8217;s somewhat unfamiliar, crimson-tinted waters.</p>
<p>Those of us who have been working in strongly-typed OO languages for a very long time &#8211; since, say, the <a href="http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612">GOF Design Patterns</a> book was first published &#8211; learned not only OO concepts and the syntactic idiosyncrasies of our language, but also <em>design patterns</em> &#8211; commonly-accepted ways of solving recurring problems in our applications.</p>
<p>If you&#8217;ve been with Java over the years &#8211; say, from Java 3 to 4 to 5, you&#8217;ve seen the language evolve to include features formerly relegated to the domain of the design pattern.  Java&#8217;s for-each loop is one such example &#8211; once that became a language feature, it was suddenly less important to know about the more generalized Iterator pattern.</p>
<p>Enter Ruby (and dynamic languages in general).  It turns out that many of the design patterns in that grand old Gang of Four book were situational &#8211; they apply generally to strongly-typed languages.  If there is one &#8220;metapattern&#8221; that describes most of the original design patterns, it is this:  &#8220;Use composition rather than inheritance in order to introduce runtime flexibility into your designs.&#8221;  Quite simple:  object composition &#8211; relationships between objects &#8211; can be changed at runtime in a strongly-typed language like Java.  Inheritance  &#8211; the only other way of introducing externally-defined capabilities to a class &#8211; cannot.</p>
<p>In Ruby, the very nature of the language makes much of that line of thinking obsolete.  Through its dynamic nature, Ruby classes can be modified programmatically, at runtime.  This statement often scares the daylights out of a Java developer when it hits them for the first time.  Upon closer inspection, though, this language feature can be used to great effect.  Behavior and associated information can be ascribed to specific instances of classes based on the <em>situation</em> in which they find themselves.  Imagine a Person object who happens to walk into a busy bank and gets into the back of a queue.  In a Ruby system describing this Person, we could blend in methods like start_waiting and elapsed_wait_time? &#8211; and those methods could then be discarded later when the Person finishes its transaction and leaves the bank.</p>
<p>How might we have done this in Java?  After all, situationally-appropriate behavior is not unique to Ruby &#8211; it&#8217;s a generalized concept that could be expressed in any language.  In Java, where class behavior is fixed at compile time, we use a specialized form of composition.  The Gang of Four called it the <a href="http://en.wikipedia.org/wiki/Decorator_pattern">Decorator</a> pattern.  So we have a situation where an inherent language feature of one language (Ruby) completely obliterates the need for a design pattern that helped legions of OO problem-solvers in earlier languages.</p>
<p>It turns out that the evolution away from patterns toward language features is something that has been noted by many others.  Suggested reading for those interested:</p>
<ul>
<li>http://designpatternsinruby.com/section01/article.html</li>
<li>http://lukeredpath.co.uk/blog/decorator-pattern-with-ruby-in-8-lines.html</li>
</ul>
]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/2012/04/04/java-to-ruby-or-learning-leading-to-unlearning/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The cloud and the 12-Factor App</title>
		<link>http://blog.jeffshurts.com/2012/04/03/the-cloud-and-the-12-factor-app/</link>
		<comments>http://blog.jeffshurts.com/2012/04/03/the-cloud-and-the-12-factor-app/#comments</comments>
		<pubDate>Tue, 03 Apr 2012 17:32:21 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Groovy/Grails]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Redpoint]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/?p=130</guid>
		<description><![CDATA[<p>Having worked for a couple years now on Rails applications deployed to cloud hosting services like EngineYard and Heroku, a certain set of &#8220;rules&#8221; have begun to emerge in the back of my head regarding this &#8220;new world&#8221; application development and deployment process.  Things that run the gamut of application development, from dependency management to rapid deployment to source control.</p>
<p>Just as a more or less holistic picture of this &#8220;new world&#8221; was beginning to form in my head, Adam Wiggins of Heroku published a very nice, quick-read &#8220;web booklet&#8221; &#8211; <a href="http://www.12factor.net">The Twelve-Factor App</a>.  It&#8217;s not deep, but does a great job of circumscribing the set of concerns one should have in mind when building an app that is destined to be deployed in the cloud.</p>
<p>If you are relatively new to cloud-based deployment of web applications, it may not be obvious that deployment to a cloud-based server should affect your application in so many ways (thread management, stateless processes, absolute separation of configuration data from source code, etc.).  Build, deploy and manage an app or two, and you&#8217;ll learn some of these lessons the hard way.</p>
<p>If you do open source development (like Ruby on Rails), learning the hard way has probably become a way of life.  Do yourself a favor and remind yourself how nice it is when someone takes the time to put up a few guideposts to mark your way, to keep you on the trail and out of the weeds (or over the cliff&#8217;s edge).  Check out this informative site.  You can get through the content in fifteen minutes.  Thirty if you take time to let the points sink in a bit.  You&#8217;ll save yourself a lot more than that if you use these concepts when you build your next hosted application.</p>
]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/2012/04/03/the-cloud-and-the-12-factor-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Small, Powerful Teams</title>
		<link>http://blog.jeffshurts.com/2011/03/21/the-magic-of-leveraging-talent/</link>
		<comments>http://blog.jeffshurts.com/2011/03/21/the-magic-of-leveraging-talent/#comments</comments>
		<pubDate>Mon, 21 Mar 2011 12:46:39 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Groovy/Grails]]></category>
		<category><![CDATA[Professional]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Redpoint]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Talent]]></category>
		<category><![CDATA[Vision]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/?p=119</guid>
		<description><![CDATA[Seymour Cray once said, "If you were plowing a field, which would you rather use? Two strong oxen or 1024 chickens?"  He was making an analogy, of course, to his super-fast processors.  I think the same idea applies to software development teams.]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/2011/03/21/the-magic-of-leveraging-talent/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby on Rails:  Serious Software?</title>
		<link>http://blog.jeffshurts.com/2011/03/20/ruby-on-rails-serious-software/</link>
		<comments>http://blog.jeffshurts.com/2011/03/20/ruby-on-rails-serious-software/#comments</comments>
		<pubDate>Sun, 20 Mar 2011 20:14:33 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Redpoint]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://blog.jeffshurts.com/?p=111</guid>
		<description><![CDATA[Ruby on Rails?  For corporate apps, with lots of users, complex business logic and lots of transactions to process?  Uh, yeah...]]></description>
		<wfw:commentRss>http://blog.jeffshurts.com/2011/03/20/ruby-on-rails-serious-software/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>A little Groovy magic &#8211; Lists and Property Accessors</title>
		<link>http://blog.jeffshurts.com/2010/05/07/a-little-groovy-magic-lists-and-property-accessors/</link>
		<comments>http://blog.jeffshurts.com/2010/05/07/a-little-groovy-magic-lists-and-property-accessors/#comments</comments>
		<pubDate>Fri, 07 May 2010 19:34:47 +0000</pubDate>
		<dc:creator>Jeff Shurts</dc:creator>
				<category><![CDATA[Groovy/Grails]]></category>
		<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; title: ; notranslate">
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/2010/05/07/a-little-groovy-magic-lists-and-property-accessors/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Grails Pagination and CriteriaBuilder</title>
		<link>http://blog.jeffshurts.com/2010/04/29/grails-pagination-and-criteriabuilder/</link>
		<comments>http://blog.jeffshurts.com/2010/04/29/grails-pagination-and-criteriabuilder/#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/2010/04/29/grails-pagination-and-criteriabuilder/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/2010/04/12/using-grails-controller-interceptors-to-avoid-rampant-testing/</link>
		<comments>http://blog.jeffshurts.com/2010/04/12/using-grails-controller-interceptors-to-avoid-rampant-testing/#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/2010/04/12/using-grails-controller-interceptors-to-avoid-rampant-testing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>All-Time Favorite Instrumental Tracks</title>
		<link>http://blog.jeffshurts.com/2010/03/11/all-time-favorite-instrumental-tracks/</link>
		<comments>http://blog.jeffshurts.com/2010/03/11/all-time-favorite-instrumental-tracks/#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/2010/03/11/all-time-favorite-instrumental-tracks/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/2010/02/02/elegant-design-customer-service-its-in-the-details/</link>
		<comments>http://blog.jeffshurts.com/2010/02/02/elegant-design-customer-service-its-in-the-details/#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/2010/02/02/elegant-design-customer-service-its-in-the-details/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

