<?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 version="2.0">
<channel>
 <title>www.thoughtworks.com aggregator</title>
 <link>http://www.thoughtworks.com/blogs/alumni</link>
 <description>www.thoughtworks.com - aggregated feeds in category ThoughtWorks Alumni</description>
 <language>en</language>
<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/thoughtworks-alumni" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="thoughtworks-alumni" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
 <title>Brian Oxley: Type Theory for the Uninitiated</title>
 <link>http://binkley.blogspot.com/2011/10/300.html</link>
 <description>&lt;p&gt;Kalani Thielen presents &lt;a href="http://blog.lab49.com/archives/3011" title="The Algebra of Data, and the Calculus of Mutation"&gt;&lt;cite&gt;The Algebra of Data, and the Calculus of Mutation&lt;/cite&gt;&lt;/a&gt;, or Type Theory for the Uninitiated.  Fine calculus a bit soft, algebra a little dull, programming a walk in the park?  Type theory is for you.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5638372-5468406148607813541?l=binkley.blogspot.com' alt='' /&gt;&lt;/div&gt;</description>
 <pubDate>Fri, 03 Feb 2012 12:17:00 -0800</pubDate>
</item>
<item>
 <title>Obie Fernandez: Can I Find an Agile, Design-Savvy iPhone Developer?</title>
 <link>http://feedproxy.google.com/~r/obie/~3/3M50jjOOAJs/can-i-find-an-agile-design-savvy-iphone-developer.html</link>
 <description>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;p&gt;DueProps has been needing an iPhone app for for a few months now. However, I don't have the time (or frankly, the inclination) to prepare a detailed specification for how it should work. I also lack tens of thousands of dollars to give to an agency to take care of it for me. The last few times I've searched for the right candidate it's been pure frustration.&lt;/p&gt;
&lt;p&gt;If I could wave a magic wand to produce my ideal iphone developer, I'd conjure someone who:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;...could start to come up with a workable design for the app after spending a few hours talking to me and familiarizing themselves with the way that DueProps works&lt;/li&gt;
&lt;li&gt;Understands iterative development. I don't need the app to be perfect or include all possible functionality all at once. The core of what I need is super simple. Login. Choose a prop. Give it to a colleague on your DueProps network or to a new user via their email address. View latest activity. The backend for all that is already there.&lt;/li&gt;
&lt;li&gt;Speaks fluent English&lt;/li&gt;
&lt;li&gt;Works independent (of an agency) for a reasonable hourly rate, say $30-50/hour&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Does such a person exist? I can't be the only person wondering...&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;EDIT:&lt;/strong&gt; If the rates I mentioned are too low and a proper rate for (as one commenter put it) a "multi-faceted pro" freelance is more like $100/hour then is it possible to get a simple, finished product in 2-3 weeks at most? Because otherwise it's seriously blowing my budget.&lt;/p&gt;
&lt;p&gt;I guess I could approach this as wanting a fixed-bid contract for my budget amount, which is $10-15k, but fixed bids have always scared the hell out of me.&lt;/p&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/obie?a=3M50jjOOAJs:Dd7rsxT_9dI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/obie?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/obie?a=3M50jjOOAJs:Dd7rsxT_9dI:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/obie?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/obie?a=3M50jjOOAJs:Dd7rsxT_9dI:RJU-JkLLmTY"&gt;&lt;img src="http://feeds.feedburner.com/~ff/obie?i=3M50jjOOAJs:Dd7rsxT_9dI:RJU-JkLLmTY" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/obie?a=3M50jjOOAJs:Dd7rsxT_9dI:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/obie?i=3M50jjOOAJs:Dd7rsxT_9dI:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/obie?a=3M50jjOOAJs:Dd7rsxT_9dI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/obie?i=3M50jjOOAJs:Dd7rsxT_9dI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/obie?a=3M50jjOOAJs:Dd7rsxT_9dI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/obie?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
 <pubDate>Fri, 03 Feb 2012 11:00:31 -0800</pubDate>
</item>
<item>
 <title>Trisha Gee: Upcoming speaking events</title>
 <link>http://mechanitis.blogspot.com/2012/02/upcoming-speaking-events.html</link>
 <description>In theory, I am busy writing material for my upcoming speaking events, rather than writing terribly &lt;a href="http://mechanitis.blogspot.com/2011/12/christmas-decorations-teach-me-lesson.html"&gt;illuminating&lt;/a&gt; posts on my blog (see what I did there?). &amp;nbsp;In actuality I am being lazy and have pretty much taken January off for a recharge.&lt;br /&gt;&lt;br /&gt;In the spirit of doing something which ticks both the event-speaking and blogging boxes, this is a quick update on the conferences I'm confirmed for so far. &amp;nbsp;Put the following dates in your diary - these are my first international solo speaking events:&lt;br /&gt;&lt;br /&gt;7th March - QCon London - &lt;a href="http://qconlondon.com/london-2012/speaker/Trisha+Gee"&gt;Concurrent Programming Using The Disruptor&lt;/a&gt;&amp;nbsp;(sadly I can't stay for the whole conference as it clashes with the only holiday I had booked for 2012).&lt;br /&gt;23rd May - GOTO Copenhagen - &lt;a href="http://gotocon.com/cph-2012/speaker/Trisha+Gee"&gt;Concurrent Programming Using The Disruptor&lt;/a&gt;&amp;nbsp;&amp;amp; War Stories.&lt;br /&gt;25-26th May - GOTO Amsterdam - &lt;a href="http://gotocon.com/amsterdam-2012/speaker/Trisha+Gee"&gt;Concurrent Programming Using The Disruptor&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The presentation will be more of a user's guide to the Disruptor than anything we've done before. &amp;nbsp;An hour isn't a lot of time to cover all the functionality everyone might want to see, so I'm still trying to work out the balance between giving an introduction/overview for those who haven't seen it before, and going into some of the cool features that have been added since I first started blogging about it. &amp;nbsp;If there's anything you would particularly like to see covered, let me know - I'll put the most frequently requested things in there.&lt;br /&gt;&lt;br /&gt;Ideally I'd run a workshop session at some point, but that will require quite a lot more preparation, so I'll only do that if there is interest in it (if someone wants to fly me somewhere interesting to do that so much the better!!).&lt;br /&gt;&lt;br /&gt;Maybe I'll see you at one of these events?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/90440057274722849-5104518460669643088?l=mechanitis.blogspot.com' alt='' /&gt;&lt;/div&gt;</description>
 <pubDate>Tue, 31 Jan 2012 23:43:00 -0800</pubDate>
</item>
<item>
 <title>Ozgur Tumer: A grand entrance, début of Language Processor</title>
 <link>http://yeahbutactually.blogspot.com/2012/01/grand-entrance-debut-of-language.html</link>
 <description>Loaded like a freight train, flyin' like an aeroplane, feelin' like a space brain...&lt;br /&gt;&lt;br /&gt;It is the début of &lt;a href="http://yeahbutactually.blogspot.com/2010/02/when-i-started-to-work-for-thoughtworks.html"&gt;Language Processor(LP)&lt;/a&gt;, my lovely java DSL framework. It is a grand entrance.&lt;br /&gt;&lt;br /&gt;We (my esteemed&amp;nbsp;colleague&amp;nbsp;Dr. Daniel Spooner and our team of&amp;nbsp;geniuses) have designed a language for a real time, ticking risk engine.&amp;nbsp;Hundreds of thousand of rows of data is pushed through hundreds of transformations every few seconds. You can join streams of data, create and calculate fields, aggregate rows, split and union data flow.&lt;br /&gt;&lt;br /&gt;With our dsl, you can define data sources, define functions, extend data sources, aggregate data, filter, union and much more. &amp;nbsp;Below is a glimpse of what can be done.&amp;nbsp;The language has a proper type system with types like int, boolean, string, real etc. and type inference.&lt;br /&gt;&lt;br /&gt;Entire business logic of how data is joined/merged/aggregated is in external files, which are converted to Java on the fly and compiled.&lt;br /&gt;&lt;br /&gt;Result is an ultra-fast and compact system, a perfect show-case for a DSL.&lt;br /&gt;&lt;br /&gt;We also generate graphs of transformations from the same language files. So it is also self-documenting. An eclipse plug-in is on the way, so is an optimising compiler.&lt;br /&gt;&lt;br /&gt;How cool is that!Check this out;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: #4c1130; font-family: 'Courier New', Courier, monospace;"&gt;/* define a table where you feed the data in */&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;let Products = table [&lt;/span&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Instrument as "" /*String type */&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Underlying as ""&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Calculate as ""&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Source as ""&lt;/span&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;ProductUpdated as 01/01/11 00:00:00 GMT /* date type */&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Model as ""&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: #4c1130; font-family: 'Courier New', Courier, monospace;"&gt;/* define a function */&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;let isSimpleInstrument = &amp;nbsp;defunc(instrument underlying model calculate) /* not a derived or calculated instrument */&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;(and (eq instrument underlying)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;(or or (eq "COMPOSITE" model) (eq "COMPOSITE2" model)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;   &lt;/span&gt;(and (or (eq "STOCK" model) (eq "stock" model)) (not (eq "C"&amp;nbsp;calculate)))))&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: #4c1130; font-family: 'Courier New', Courier, monospace;"&gt;/* extend tables with calculations, you can get the result of any transformation */&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;let ExtendProduct = extend Products with [&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; I&lt;span class="Apple-style-span" style="white-space: normal;"&gt;sSimpleInstrument&amp;nbsp;&lt;/span&gt;&lt;/span&gt;as&amp;nbsp;isSimpleInstrument(Instrument Underlying Model Calculate)&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: #4c1130; font-family: 'Courier New', Courier, monospace;"&gt;/* type interference; as Instrument and Underlying are both strings so is the derived field Underlying. */&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Underlying as (if &lt;span class="Apple-style-span" style="white-space: pre;"&gt;I&lt;span class="Apple-style-span" style="white-space: normal;"&gt;sSimpleInstrument&lt;/span&gt;&lt;/span&gt;&amp;nbsp;Instrument Underlying)&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;let Prices = table [&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Instrument as ""&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;PriceSource as ""&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;RIC as ""&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Currency as ""&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;Price as 0.0 /* real type */&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;PriceTimestamp as 01/01/11 00:00:00 GMT&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;ReutersLast as 0.0&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;ReutersClose as 0.0&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;ReutersBid as 0.0&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;ReutersAsk as 0.0&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: #4c1130; font-family: 'Courier New', Courier, monospace;"&gt;/* join tables */&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;let PriceProductJoin = join&amp;nbsp;ExtendProduct&amp;nbsp;with Prices on (eq Underlying Instrument)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8722491094839001547-799840311535695069?l=yeahbutactually.blogspot.com' alt='' /&gt;&lt;/div&gt;</description>
 <pubDate>Tue, 31 Jan 2012 05:36:00 -0800</pubDate>
</item>
<item>
 <title>Obie Fernandez: Rendering Collections of Heterogeneous Objects in Rails 3.2</title>
 <link>http://feedproxy.google.com/~r/obie/~3/HqmUy5WI5LM/rendering-collections-of-heterogeneous-objects-in-rails-32.html</link>
 <description>&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;p&gt;This &lt;a href="https://github.com/rails/rails/commit/bf812074fd55e7dcfa426d6c9bfd4d8d68922194" target="_blank"&gt;commit&lt;/a&gt; by Grant Hutchins &amp;amp; Peter Jaros back in July 2011 gives ActiveModels the ability to define their own partial paths by implementing a &lt;strong&gt;to_partial_path&lt;/strong&gt; method. (You can find a great explanation of this killer new feature on &lt;a href="http://blog.plataformatec.com.br/2012/01/my-five-favorite-hidden-features-in-rails-3-2/" target="_blank"&gt;José Valim's blog post about it&lt;/a&gt;. Just scroll down to #4 Custom Partial Paths.)&lt;/p&gt;
&lt;p&gt;I'm blogging about it here, because it impacts a technique that I described in May 2011 as &lt;a href="http://blog.obiefernandez.com/content/2011/05/rending-collections-of-heterogeneous-objects-in-rails.html" target="_self"&gt;Rendering Heterogeneous Collections of Objects in Rails&lt;/a&gt;. If you happen to be using that technique or anything like it involving the use of ActiveModel's &lt;strong&gt;partial_path&lt;/strong&gt; method, you'll get deprecation warnings like this when upgrading to Rails 3.2:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'andale mono', times;"&gt;DEPRECATION WARNING: partial_path is deprecated and will be removed from Rails 3.2 (ActiveModel::Name#partial_path is deprecated. Call #to_partial_path on model instances directly instead.). (called from partial_path at .../config/initializers/partial_path.rb:12)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In this blog post I describe how to update my technique and get rid of the deprecation warning.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;heterogeneous&lt;/em&gt; aspect of my technique had to do with rendering collections of STI objects that all inherited from a single &lt;strong&gt;Event&lt;/strong&gt; base class. For organizational reasons, I wanted to put all my disparate event partials in a single &lt;strong&gt;app/view/events&lt;/strong&gt; directory. Without the hack, they'd need to be in their own &lt;strong&gt;view/foo_events/_foo_event.html.erb&lt;/strong&gt; partials. Ugh.&lt;/p&gt;
&lt;p&gt;In Rails 3.2, instead of having to monkey patch the framework to fix that crap, I can just implement &lt;strong&gt;to_partial_path&lt;/strong&gt; on the &lt;strong&gt;Event&lt;/strong&gt; base class like this:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'andale mono', times;"&gt;class Event&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'andale mono', times;"&gt;  def to_partial_path&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: 'andale mono', times;"&gt;    "events/#{self.class.name.underscore}"&lt;/span&gt;&lt;br&gt;&lt;span style="font-family: 'andale mono', times;"&gt;  end &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'andale mono', times;"&gt;end&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Ahh, that's much cleaner. Unfortunately, there's still a catch, but only if you use controller namespaces.&lt;/p&gt;
&lt;p&gt;Rails 3.2 keeps the annoying merge of the namespace prefix as part of the generated partial path even if you override it using &lt;strong&gt;to_partial_path&lt;/strong&gt;. The good news is that it is easier to get rid of it in Rails 3.2 than before. The monkeypatch in my earlier blog post now becomes:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'andale mono', times;"&gt;ActionView::PartialRenderer.class_eval do&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'andale mono', times;"&gt; &lt;/span&gt;&lt;span style="font-family: 'andale mono', times;"&gt; private&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'andale mono', times;"&gt;  def merge_prefix_into_object_path(pfx, path)&lt;br&gt;    path&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: 'andale mono', times;"&gt;  end &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'andale mono', times;"&gt;end&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;What this little bit of duck punching does is to ensure that when you try to render a collection of objects, it will always return the same partial path regardless of whether you are inside a controller namespace or not. I feel that behavior should be default or at least optional (which is why I describe the feature as annoying.) Let me know if you think it's worth submitting a patch.&lt;/p&gt;
&lt;p&gt;Incidentally, in his &lt;a href="http://blog.plataformatec.com.br/2012/01/my-five-favorite-hidden-features-in-rails-3-2/" target="_blank"&gt;blog post mentioned above&lt;/a&gt; Jose mentions needing to add an &lt;strong&gt;as: &lt;/strong&gt;parameter to your call to render, like this:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'andale mono', times;"&gt;render :partial =&amp;gt; @activities, :as =&amp;gt; :activity&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;In my testing and examination of the underlying Rails code, it is clear that the &lt;strong&gt;:as&lt;/strong&gt; option is not necessary. The &lt;strong&gt;PartialRenderer&lt;/strong&gt; object always checks for the existence of a &lt;strong&gt;to_partial_path&lt;/strong&gt; method on the object being rendered and calls it if present. &lt;/p&gt;
&lt;p&gt;One more thing. &lt;a href="https://github.com/rails/rails/blob/efed2d56e22069fc142016f398625588684ce008/actionpack/lib/action_view/renderer/partial_renderer.rb" target="_blank"&gt;Currently&lt;/a&gt; the documentation states the following (italics mine):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Instead of explicitly naming the location of a partial, you can also let PartialRenderer do the work and pick the proper path by checking `to_proper_path` method. If the object passed to render is a collection, &lt;em&gt;all objects must return the same path&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I'm not quite sure why it says that all objects must return the same path, or why that would even be considered desirable behavior (it's really not!) The good news is that I can verify for you that it does work to return different partial paths within the collection, in other words, you can still do the rendering heterogeneous objects trick. In fact, depending on your naming convention, you may even get correctly name local variables in your partial for free.&lt;/p&gt;
&lt;p&gt;The following method determines what to call your partial's automatic local variable corresponding to the current item of the collection being rendered:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'andale mono', times;"&gt;def retrieve_variable(path)&lt;br&gt;&lt;/span&gt;&lt;span style="font-family: 'andale mono', times;"&gt;  variable =&lt;br&gt;    @options[:as].try(:to_sym) || path[%r'_?(\w+)(\.\w+)*$', 1].to_sym&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'andale mono', times;"&gt;  variable_counter = :"#{variable}_counter" if @collection&lt;br&gt;  [variable, variable_counter]&lt;br&gt;end&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;That regex is a little tricky, but whether it's the intentional behavior or not, it's going to grab whatever is between the last underscore of your partial name and the dot to use as the variable name. In the case of my own Event hierarchy, that means each partial will get its own &lt;strong&gt;event&lt;/strong&gt; local variable, even though the partials are named _user_created_event, _nomination_event, etc.&lt;/p&gt;
&lt;p&gt;Perfect. Now to hope someone doesn't fuck it up in a future release thinking it's a bug :)&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: 'andale mono', times;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/obie?a=HqmUy5WI5LM:S7ALpJ9tmRc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/obie?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/obie?a=HqmUy5WI5LM:S7ALpJ9tmRc:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/obie?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/obie?a=HqmUy5WI5LM:S7ALpJ9tmRc:RJU-JkLLmTY"&gt;&lt;img src="http://feeds.feedburner.com/~ff/obie?i=HqmUy5WI5LM:S7ALpJ9tmRc:RJU-JkLLmTY" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/obie?a=HqmUy5WI5LM:S7ALpJ9tmRc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/obie?i=HqmUy5WI5LM:S7ALpJ9tmRc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/obie?a=HqmUy5WI5LM:S7ALpJ9tmRc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/obie?i=HqmUy5WI5LM:S7ALpJ9tmRc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/obie?a=HqmUy5WI5LM:S7ALpJ9tmRc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/obie?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description>
 <pubDate>Mon, 30 Jan 2012 16:13:27 -0800</pubDate>
</item>
<item>
 <title>Elizabeth Keogh: The Real Cost of Change</title>
 <link>http://lizkeogh.com/2012/01/30/the-real-cost-of-change/</link>
 <description>&lt;h3&gt;We have a strange desire for control.&lt;/h3&gt;
&lt;p&gt;I was in a planning meeting with my project manager and several of the devs. &amp;#8220;What happened?&amp;#8221; the project manager said. &amp;#8220;Why did this one story take so long?&amp;#8221;&lt;/p&gt;
&lt;p&gt;&amp;#8220;There was some functionality we needed and didn&amp;#8217;t know about,&amp;#8221; I replied. &amp;#8220;We managed to get it in before the deadline, though.&amp;#8221; The business had been quite happy with that, and they were notoriously hard to please.&lt;/p&gt;
&lt;p&gt;&amp;#8220;If they&amp;#8217;re going to change their mind like this,&amp;#8221; the PM replied, &amp;#8220;we&amp;#8217;re going to have to introduce some kind of change control.&amp;#8221;&lt;/p&gt;
&lt;p&gt;&amp;#8220;Please don&amp;#8217;t,&amp;#8221; I begged. &amp;#8220;If you do that, the business will spend more time investing in getting things right to start with.&amp;#8221;&lt;/p&gt;
&lt;p&gt;&amp;#8220;Exactly.&amp;#8221;&lt;/p&gt;
&lt;p&gt;&amp;#8220;But they&amp;#8217;ll still get it wrong. No amount of planning would have spotted that missing piece before we showed it to them! When they get it wrong now, though, they&amp;#8217;ll encounter the change control and they&amp;#8217;ll want to spend even &lt;em&gt;more&lt;/em&gt; time getting it right first time. And they&amp;#8217;ll &lt;em&gt;still&lt;/em&gt; get it wrong, but now we&amp;#8217;ll have made it more expensive for them to be wrong. We&amp;#8217;ll have a formal process which means it takes even longer for us to find out what&amp;#8217;s missing, by which time us devs will have to work to remember the code and the change will take longer. It will slow us down. So they&amp;#8217;ll see that, and spend even &lt;em&gt;more&lt;/em&gt; time trying to get it right, and before you know it they&amp;#8217;ll be planning whole projects up front.&amp;#8221;&lt;/p&gt;
&lt;p&gt;We have a word for that. It&amp;#8217;s called &lt;em&gt;Waterfall&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://imgur.com/PbhfM"&gt;&lt;img src="http://i.imgur.com/PbhfM.png" alt="Waterfall's reinforcing feedback loop" width="80%" height="80%" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;That desire to control change creates a reinforcing feedback loop, in which the cost of change makes us want to invest up-front, which makes the change expensive later on, which makes us want to invest up-front, and so on.&lt;/p&gt;
&lt;p&gt;In this case, it would have been pointless, except as a way of shifting blame and risk back to the analysts (and this was an internal project). The cost of change was quite low; we had clean code with a good suite of tests. It was only the cost of &lt;em&gt;discovery&lt;/em&gt;, and the implementation that followed, that was really expensive.&lt;/p&gt;
&lt;h3&gt;Don&amp;#8217;t confuse the cost of discovery with the cost of change.&lt;/h3&gt;
&lt;p&gt;Discovering something later on only costs more than planning for it if you&amp;#8217;ve made a &lt;em&gt;commitment&lt;/em&gt; to something else.&lt;/p&gt;
&lt;p&gt;In fact, if you don&amp;#8217;t plan for it, it can cost less. The newly-discovered knowledge will be fresh in everyone&amp;#8217;s minds. Because the ideas haven&amp;#8217;t been known for long, nobody&amp;#8217;s mentally committed to them either, which makes them easier to question and clarify.&lt;/p&gt;
&lt;p&gt;This is even more important when there&amp;#8217;s a chance that the analysis might be wrong (and there&amp;#8217;s always that chance; we learnt this from Waterfall). If you plan for something that you later have to revert, you&amp;#8217;ve introduced a cost of change right there. Perhaps the cost is just changing some documents. Perhaps the developers have designed for the plan, and built on top of the thing which needs changing.&lt;/p&gt;
&lt;p&gt;But we need to do &lt;em&gt;some&lt;/em&gt; planning, right? Otherwise the chances of us being wrong and building on top of the wrong thing are even bigger, and there&amp;#8217;s even more chance that we&amp;#8217;ll have made commitments the wrong way. So how should we plan?&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve got few more guidelines I&amp;#8217;d like to share. Here&amp;#8217;s the first:&lt;/p&gt;
&lt;h3&gt;Keep the cost of change low.&lt;/h3&gt;
&lt;p&gt;This is more important even than planning, because there&amp;#8217;s &lt;em&gt;always&lt;/em&gt; a chance that we&amp;#8217;ll get something wrong.&lt;/p&gt;
&lt;p&gt;This is what we&amp;#8217;re aiming for: the ideal, low cost of change on an Agile project.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://imgur.com/XfR4U"&gt;&lt;img src="http://i.imgur.com/XfR4U.png" alt="The wonderfully low cost of change on a very nice Agile project." width="80%" height="80%" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The first thing to notice about this is that the cost of change is &lt;em&gt;not zero&lt;/em&gt;. That&amp;#8217;s going to become important in the next section, and it&amp;#8217;s what drives the team&amp;#8217;s desire for change control and starts kicking off that Waterfall loop.&lt;/p&gt;
&lt;p&gt;The second thing to notice is that this bears little resemblance to actual, real Agile projects.&lt;/p&gt;
&lt;p&gt;On a real Agile project, it&amp;#8217;s likely that we have fluctuating levels of stress, concentration, experience and desire for feedback. All of these &amp;#8211; or lack of them &amp;#8211; will lead us to occasionally write code that is, shall we say, less than ideal.&lt;/p&gt;
&lt;p&gt;It takes discipline to write code that&amp;#8217;s easy to change. On a real Agile project, we tend not to do it all the time. Oh, we might &lt;em&gt;say&lt;/em&gt; we do, but we don&amp;#8217;t. Not always. And if we do, our team-mates don&amp;#8217;t. The real skill isn&amp;#8217;t in writing clean code &amp;#8211; it&amp;#8217;s in cleaning up the horrible mess we made the week before. And it takes &lt;em&gt;even more discipline&lt;/em&gt; to do it afterwards, especially if you&amp;#8217;re under pressure to just hack the next working thing in too.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://imgur.com/A7vgE"&gt;&lt;img src="http://i.imgur.com/A7vgE.png" alt="The real cost of change on an Agile project, showing how we clean up after ourselves." width="80%" height="80%" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If we don&amp;#8217;t clean up and keep that cost of change low, we&amp;#8217;re making a commitment to the wrong thing. The longer that commitment stays in place, the higher the cost of change will become. We&amp;#8217;ll find ourselves on that Waterfall cost of change curve, and the longer we&amp;#8217;re on it, the more expensive it is.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve found the skill to clean up afterwards is even more important in high-learning projects, where a lot of the technology or domain is new, at least to the team. There&amp;#8217;s no point in writing tests up front for a class when you don&amp;#8217;t even know what&amp;#8217;s possible, or what other frameworks and libraries will do for you, or what the business really want. In those environments, rather than TDD or BDD, teams tend to &lt;em&gt;Spike and Stabilize&lt;/em&gt;. The spikes aren&amp;#8217;t really prototypes &amp;#8211; they&amp;#8217;re small pieces of features, often with hard-coded data behind them, designed to get some feedback about techology or requirements. &lt;a href="http://dannorth.net/2011/01/15/on-craftsmanship/"&gt;Dan North, who gave me the term,&lt;/a&gt; might write more about this later if we ask nicely, but for this post, we can simply bear in mind that the skill to stabilize later &amp;#8211; ensuring that the cost of change is &lt;em&gt;lowered&lt;/em&gt; &amp;#8211; is often more important than the skill to keep the cost of change low up-front.&lt;/p&gt;
&lt;p&gt;Because we get it wrong too.&lt;/p&gt;
&lt;h3&gt;Assume you got it wrong.&lt;/h3&gt;
&lt;p&gt;Human beings are hard-wired to try and get things right, and to pretend that they did even when they didn&amp;#8217;t. I love &lt;a href="http://en.wikipedia.org/wiki/List_of_cognitive_biases"&gt;this list of cognitive biases on Wikipedia&lt;/a&gt;. These are just some of the ways in which we get it wrong and don&amp;#8217;t even notice.&lt;/p&gt;
&lt;p&gt;If we assume that we got it wrong, then we start to look for &lt;em&gt;feedback&lt;/em&gt;, and quickly. This is difficult for most human beings. We much prefer to get validation than feedback; to be told that we did it right, rather than finding out what we did wrong. Our brain gives us these little kicks of nice chemicals when we learn that we did something right, and it feels much better than the other kind.&lt;/p&gt;
&lt;p&gt;If we can remember, though, that we probably got it wrong, our focus will change. Instead of trying to invest in good requirements and nice code, we&amp;#8217;ll try to find out what we got wrong in the things we&amp;#8217;ve already done. Of course, we need to invest in stabilizing what we&amp;#8217;ve done, or the cost of change goes up, and that will make it more expensive later if we find out we were wrong, which is the assumption we were trying to make in the first place&amp;#8230; ah, the paradox!&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s a fine balance to be struck between getting quick feedback &amp;#8211; often itself an expensive proposition, given the business of most domain experts &amp;#8211; and getting it right up front. So where does the balance lie?&lt;/p&gt;
&lt;h3&gt;Don&amp;#8217;t sweat the petty stuff.&lt;/h3&gt;
&lt;p&gt;If it&amp;#8217;s easy to change, don&amp;#8217;t worry about it. Analysts, learn what&amp;#8217;s easy to change. Typos, colours, fonts, labels, sizes, placement on the screen, tab order, an extra field&amp;#8230; these are all usually easy to change, and do not normally need to be specified up-front. Even if you have a particular style you want to see on a page or form, this can usually be abstracted out and changed later &amp;#8211; just let the devs know that you want that consistency at some point.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s more important for us to know the rough shape of what you want to see, and the flow and process of that information. We don&amp;#8217;t want to know every field on an order item. We just want to know that it needs to be sent to the warehouse and stored locally because you&amp;#8217;re going to check the money in the till and count the stock. The fine detail of that is pretty easy to change, so we can get feedback on it later. Getting the fine detail right would definitely be an investment, and we might have got the big picture wrong.&lt;/p&gt;
&lt;h3&gt;Deliberately discover things you&amp;#8217;ve never done before.&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://dannorth.net/2010/08/30/introducing-deliberate-discovery/"&gt;Dan North wrote an excellent post on Deliberate Discovery&lt;/a&gt;, and I&amp;#8217;ve been using it to manage risk on my projects for a while now. It&amp;#8217;s one of the most important tools in my toolbox, along with Real Options to which it&amp;#8217;s strongly related, so I want to cover how I use it here.&lt;/p&gt;
&lt;p&gt;I really like using &lt;a href="http://en.wikipedia.org/wiki/Cynefin"&gt;Cynefin&lt;/a&gt; to help me work out what to target for discovery. We treat a lot of software as if it&amp;#8217;s &lt;em&gt;complex&lt;/em&gt;, and we talk about self-organising teams and high learning environments, but in reality there are huge chunks in most applications which follow well-established rules, have been done a thousand times before and probably have libraries or third-party apps to do the job for you. They&amp;#8217;re not complex. They&amp;#8217;re &lt;em&gt;complicated&lt;/em&gt;. They require the application of a bit of expertise, and are likely to be done right and never changed again. User registration and logging in are great examples of this. You don&amp;#8217;t need a big, thick document to describe them. The fine details might change, of course, but we already know not to sweat the petty stuff.&lt;/p&gt;
&lt;p&gt;It is &lt;em&gt;OK to plan some aspects of a system as if it&amp;#8217;s Waterfall&lt;/em&gt; &amp;#8211; for instance, deciding up-front whether you want to use your own login or let Google authenticate. Even better than requirements documents, and quicker, is to say, &amp;#8220;It&amp;#8217;s user registration. Make it work like Twitter&amp;#8217;s, but we also need the user&amp;#8217;s loyalty card number. We should offer to send them a card if they don&amp;#8217;t have one.&amp;#8221; Dan North calls this pattern &amp;#8220;Ginger Cake&amp;#8221; &amp;#8211; it&amp;#8217;s like a chocolate cake, but with ginger. He &lt;em&gt;even cuts and pastes code&lt;/em&gt;. And it&amp;#8217;s OK! Honestly, it is! This code is also absolutely prime for TDDing &amp;#8211; if you actually have to write it yourself, that is, since it&amp;#8217;s been done before so someone&amp;#8217;s probably written something to do it for you already. You can also give this code to junior devs, for whom it&amp;#8217;s new, and guide them in TDDing, making it perfect pair-programming territory. Everything you have ever been told about Agile software development applies particularly in this place.&lt;/p&gt;
&lt;p&gt;Fortunately, most applications have a minimum set of requirements that they share with other, similar applications. David Anderson calls these &lt;em&gt;commodities&lt;/em&gt; &amp;#8211; table stakes that you have to have just to play the game &amp;#8211; so *most* code in an application will end up going this way.&lt;/p&gt;
&lt;p&gt;The places in which we&amp;#8217;re most likely to get it wrong, and need fast feedback, are places where we&amp;#8217;re doing something &lt;em&gt;new&lt;/em&gt;. They might be technological, particular to a domain, or just things that the team themselves have never looked at. My favourite book for understanding risk is &lt;a href="http://www.amazon.com/Waltzing-Bears-Managing-Software-Projects/dp/0932633609/"&gt;&amp;#8220;Waltzing with Bears&amp;#8221;&lt;/a&gt;, which starts the first chapter with, &amp;#8220;If a project has no risks, don&amp;#8217;t do it.&amp;#8221; It&amp;#8217;s these new, risky aspects of the project that differentiate it from others and make it valuable in the first place!&lt;/p&gt;
&lt;p&gt;For new and risky aspects of a project, the best thing to do is assume you got it wrong, and work out how quickly you can get feedback on how wrong you are.&lt;/p&gt;
&lt;h3&gt;Any new or unknown aspect of a project will need to be changed.&lt;/h3&gt;
&lt;p&gt;I was chatting to one of our analysts. &amp;#8220;I can see this feature is in analysis at the moment,&amp;#8221; I said. &amp;#8220;Does that mean it&amp;#8217;s the next thing we want the developers to do?&amp;#8221;&lt;/p&gt;
&lt;p&gt;&amp;#8220;Oh, no,&amp;#8221; the analyst said. &amp;#8220;It&amp;#8217;s only there because the analysis is quite complex. It&amp;#8217;s all new stuff, so we&amp;#8217;re having to be careful with it and it&amp;#8217;s taking a bit of time. Once we get the analysis done, the development should be very easy, so we&amp;#8217;ll do it later.&amp;#8221;&lt;/p&gt;
&lt;p&gt;&amp;#8220;Oh, the development will be easy, I&amp;#8217;m sure&amp;#8230; but wouldn&amp;#8217;t you like to find out what you did wrong now, rather than later, while it&amp;#8217;s still fresh in your mind?&amp;#8221;&lt;/p&gt;
&lt;p&gt;The analyst smiled. The company was very much more used to Waterfall, and the idea that it was OK to get it wrong was something very new.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s OK to get it wrong, as long as you get feedback quickly, while the cost of change is still low. By working out which parts of a project are unknown or new, and targeting those &lt;em&gt;first&lt;/em&gt;, we make small investments while the cost of change is still low.&lt;/p&gt;
&lt;h3&gt;Keep your options open &amp;#8211; do the risky stuff first and keep tech debt low.&lt;/h3&gt;
&lt;p&gt;Anyone who&amp;#8217;s run into me at conferences will know how much I love Real Options, and it&amp;#8217;s really at the heart of the cost of change.&lt;/p&gt;
&lt;p&gt;The only reason change costs more is because of the &lt;em&gt;commitment&lt;/em&gt; that we already made. Chris Matts describes technical debt as an &amp;#8220;unhedged call option&amp;#8221;. He says, &amp;#8220;You give someone the right to buy Chocolate Santas from you at 30 cents each. That&amp;#8217;s fine, as long as the price of chocolate stays low. As soon as it goes up, you still have to pay to make the Santas, and now you&amp;#8217;re in trouble and your company is going bust, because you didn&amp;#8217;t give yourself the option to get the chocolate somewhere else.&amp;#8221;&lt;/p&gt;
&lt;p&gt;Similarly, technical debt is absolutely fine until we&amp;#8217;re called on to act, and act fast. At that point, we&amp;#8217;re in trouble. This is the biggest reason for keeping the cost of change low &amp;#8211; because it gives us the option for change, later. It&amp;#8217;s a frequently-cited reason for replacing legacy projects &amp;#8211; and, bizarrely, often forgotten when the pressure mounts and the business want their replacement app.&lt;/p&gt;
&lt;p&gt;This isn&amp;#8217;t helped by &lt;a href="http://dannorth.net/2009/07/01/the-perils-of-estimation/"&gt;common practices of estimation and the associated promises&lt;/a&gt;, which often lead to that pressure building up in the first place. Rather than making these promises up-front, why not try the risky bits first? I often hard-code data so that I can get feedback on a new UI early, or I spike something out using a new library or framework, or connect to that third-party application just to see what the API is really like to use, or have a chat with the team writing that other system we&amp;#8217;re going to need in June, so I can find out how communicative and receptive to feedback they are. Doing this means that we give ourselves the most time to recover from any unexpected discoveries, and we can worry about the more predictable aspects of a system later.&lt;/p&gt;
&lt;p&gt;Once we&amp;#8217;ve got spikes out of the way, adding tests to act as documentation and examples for any legacy code we&amp;#8217;ve created, cleaning it up so it&amp;#8217;s self-commenting, ensuring that architectural and modular components are properly decoupled, etc., all help us to &lt;em&gt;stabilize&lt;/em&gt; the code. At the same time, the effort involved in creating stable code is itself an investment. If there&amp;#8217;s a good chance that the code might be wrong, it could be worth getting feedback on &lt;em&gt;that&lt;/em&gt; &amp;#8211; knocking up integration tests, showing it to the business, testing it, getting it live &amp;#8211; before it&amp;#8217;s made stable.&lt;/p&gt;
&lt;p&gt;That way, the commitment made is small, and the cost of change is low.&lt;/p&gt;
&lt;p&gt;Just remember to clean up and keep it that way!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Dan is currently writing about &lt;em&gt;Spike and Stabilize&lt;/em&gt; and &lt;em&gt;Ginger Cake&lt;/em&gt; as part of his &amp;#8220;Patterns of Effective Delivery&amp;#8221;. If you&amp;#8217;re interested in finding out more, you might like to watch his &lt;a href="http://vimeo.com/24681032"&gt;Roots talk&lt;/a&gt; on the topics.&lt;/p&gt;</description>
 <pubDate>Mon, 30 Jan 2012 04:37:42 -0800</pubDate>
</item>
<item>
 <title>Ted Neward: Top Developer Resources?</title>
 <link>http://blogs.tedneward.com/2012/01/28/Top+Developer+Resources.aspx</link>
 <description>&lt;p&gt;
While going through some spam email (well, technically not spam, since I willingly
signed up for the ads/product-centric-newsletters, but that is just a mouthful to
say), I ran across the &lt;a href="http://www.appdesignvault.com/top-mobile-app-development-resources" target="_blank"&gt;App
Design Vault 32 Top Resources Mobile App Developers Should Know About list&lt;/a&gt;, and
had a look. I was somewhat disappointed at the fact that they were all iOS resources,
leaving the Android and Windows Phone crowd out in the cold, not to mention Java,
.NET, Ruby, and others shivering on the back porch as well.
&lt;/p&gt;
&lt;p&gt;
So, I figured, why not build one that seeks to be a tad more all-encompassing? And
rather than try and impose my own sense of order upon the world, and limit it to my
own experiences, I choose instead to crowdsource the thing, and let you tell me what
you think the top developer resources are.
&lt;/p&gt;
&lt;p&gt;
Because these things have to have some kind of structure, in order to effectively
collate all the resources that will be thrown at me, I’m going to ask that you
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Limit your list to five resources.&lt;/em&gt; The final list will likely (I hope) contain
a lot more, but if you just give me the top five resources you think are invaluable
to you as a developer, it’ll make the list more well-considered and pare it down to
just the essential stuff you think about.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Keep the lists somewhat tech-focused.&lt;/em&gt; Not in the sense that I don’t want
to know about agile resources and what-not, but that I want to hear what your top
.NET five are, your top Java five, and so on. Of course, if you really want to just
come up with one list across several platforms or categories, go for it. Yours is
the comment box, after all. :-)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
And if you work for a company or you own a product, please feel free to nominate your
tool of choice… so long as there are four others that go along with your baby. Fair
is fair, after all. ;-)
&lt;/p&gt;
&lt;p&gt;
And yes, for those who are curious, I will of course inject my own into the list,
but I just had this thought latch into my head a few minutes ago, and haven’t compiled
my own list yet, so I need a little time to think about it, too.
&lt;/p&gt;
&lt;p&gt;
Roughly speaking, categories that come to mind are: .NET, Java (which I’m assuming
to mean mostly enterprise/Java-web kinds of things, but hey, if Swing is your thing,
go for it…), Ruby, Web, Game development (any platform), Android, iOS, MacOS, C++
(by which I really mean “any language that compiles to native code”, a la Haskell,
C, Delphi, …), and what the hell, PHP. (Perl guys, I’m going to automatically put
“Any book teaching some other language” at #1 on your list, just to tweak your nose
a bit.) If you have some other categorization, sure, throw that at me, too.
&lt;/p&gt;
&lt;p&gt;
The App Design Vault broke their resources down into a few categories too: Books,
Tutorials, Tools, Sites, Forums, Marketing, and Design. Obviously there’s a pretty
strong website bias in there (Tutorials, Sites, Forums, Marketing and Design all usually
involve websites of one form or another), but feel free to toss in Conferences, Magazines,
and whatever else seems useful to you.
&lt;/p&gt;
&lt;p&gt;
Think of it like this: if a programmer writing an app for you were to be stuck on
a deserted island with nothing but a laptop and an extremely limited Internet connection,
what five things would you want him/her to have with them or access to? (Perhaps more
accurately, “a fully-available Internet connection but a very limited amount of time
to do anything other than work on your app” is the better way to phrase that...)
&lt;/p&gt;
&lt;p&gt;
And please, no flames or criticism of anybody else’s list. Email ‘em to me, if you’d
prefer. (And if you’re reading this through one of the post portals—a la Reddit or
DZone—please comment on the original site, tedneward.com, or I probably won’t see
your comments.)
&lt;/p&gt;
&lt;p&gt;
Once I have what feels like a sizable list and the suggestions are tapering off, I’ll
update this post with the results. No points or awards or endorsements intended—I
just want to compile something I think would be useful.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=718af7ab-cb7a-4e95-af71-4f6f98e297b7" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
 <pubDate>Sat, 28 Jan 2012 02:03:48 -0800</pubDate>
</item>
<item>
 <title>Joshua Graham: Viewing full Facebook site on mobile device</title>
 <link>http://feedproxy.google.com/~r/VirtualSurreality/~3/jc4hPVmNnwc/</link>
 <description>&lt;div class="tweetmeme_button" style="float: right; margin-left: 10px;"&gt;
			&lt;a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fgrahamis.com%2Fblog%2F2012%2F01%2F26%2Fviewing-full-facebook-site-on-mobile-device%2F"&gt;&lt;br /&gt;
				&lt;img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fgrahamis.com%2Fblog%2F2012%2F01%2F26%2Fviewing-full-facebook-site-on-mobile-device%2F&amp;amp;source=delitescere&amp;amp;style=normal&amp;amp;service=bit.ly&amp;amp;b=2" height="61" width="50" /&gt;&lt;br /&gt;
			&lt;/a&gt;
		&lt;/div&gt;
&lt;p&gt;A plethora of useless answers out there. Here it is:&lt;/p&gt;
&lt;p&gt;On an iOS device&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Scroll page so you go past the top of the Facebook page and can see the browser address bar&lt;/li&gt;
&lt;li&gt;Change the &lt;code&gt;m&lt;/code&gt; to &lt;code&gt;www&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Remove the &lt;code&gt;?_rdr#~!/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Press Go&lt;/li&gt;
&lt;p&gt;You may have some fiddling to get the auto-appearing drop down tools on posts but they will come.&lt;/p&gt;
&lt;p&gt;Enjoy.&lt;/ol&gt;
&lt;img src="http://feeds.feedburner.com/~r/VirtualSurreality/~4/jc4hPVmNnwc" height="1" width="1"/&gt;</description>
 <pubDate>Thu, 26 Jan 2012 20:50:43 -0800</pubDate>
</item>
<item>
 <title>Ted Neward: When are servers not servers?</title>
 <link>http://blogs.tedneward.com/2012/01/25/When+Are+Servers+Not+Servers.aspx</link>
 <description>&lt;p&gt;
In his Dr Dobb’s overview, Andrew Binstock talks about the prevalence of low-cost,
low-powers and suggest in the title of the piece that they have begun their steady
ascent over more traditional servers. His concluding statement, in fact, suggests
that they will replace the “pizza box” servers we have come to know and love.
&lt;/p&gt;
&lt;p&gt;
Ironically, to me, the notion of a “server” still conjures up images of row upon row
of full-tower machines, whirring away. In fact, I have one of those under my work
desk at home, doing… nothing. Right now I have it more or less permanently switched
off.
&lt;/p&gt;
&lt;p&gt;
Andrew and I have disagreed on things before, but on this score, he’s right: the machines
we commonly call “servers” are, step by step, slowly but surely, becoming smaller,
quieter, lighter, better power-friendly, and all the other things we have traditionally
associated with the client side of the client/server equation. It’s not new: I have
a couple of friends who, in order to do “cloud” or “cluster” presentations, carry
around with them a small private cloud. One of them carries around (as in, with them
to conferences and such) about a half-dozen laptops, the other, a custom-made rack
of Mac Minis, a router, and other accoutrements. Yes, if you attend TechEd, you probably
know exactly whom I mean.
&lt;/p&gt;
&lt;p&gt;
But this raises some interesting questions. If servers are becoming smaller and lighter
and are still fast enough to be considered servers, what does this have to say about
infrastructure? Andrew touches on it briefly,
&lt;/p&gt;
&lt;blockquote&gt; 
&lt;p&gt;
This model of low-cost, low-power devices is the way of the future. What I am describing
here is not terribly different than building your own personal cloud from inexpensive
machines. If you had chosen to keep the $300, you could have gotten this much from
Rackspace's cloud server: 512MB RAM and 20GB HDD running Linux. That's not close to
as much horsepower as my machine delivers However, it gives you two advantages: You
have no additional ongoing costs (power consumption, parts replacement), and because
it's off site, you have an instant off-site backup of your code base. Other companies,
such as IntoVPS.com, give you about twice Rackspace's resources for the same price.
Eventually, the pricing of cloud options will drop to close to the low-power, on-site
devices, I expect. (Source: &lt;a title="http://drdobbs.com/tools/232500406?cid=DDJ_nl_mdev_2012-01-25_h&amp;amp;elq=5c23117c5cff4d06820726bd0294693a" href="http://drdobbs.com/tools/232500406?cid=DDJ_nl_mdev_2012-01-25_h&amp;amp;elq=5c23117c5cff4d06820726bd0294693a"&gt;http://drdobbs.com/tools/232500406?cid=DDJ_nl_mdev_2012-01-25_h&amp;amp;elq=5c23117c5cff4d06820726bd0294693a&lt;/a&gt;)
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
… but putting the discussion of “on-premise” vs “cloud” off to one side for a moment,
it raises a more interesting question: if servers are small enough to carry around
with us, are they still servers? Historically, the server has always been the machine
in the data center, but if we have tools that allow servers to synchronize data between
them easily (such as we see going on in tools like Dropbox or Evernote), and the servers
are small and portable enough to fit in our pockets, then are they still servers?
&lt;/p&gt;
&lt;p&gt;
Think about this for a moment: the servers that Andrew describes (“a 1.8GHz dual-core
Intel Atom chip, 2GB RAM, 250 GB SATA, HDMI, 6 ea. USB, Wifi, and GbE” and “a dual-core
1GHz ARM-based Tegra chip from Nvidia, had robust Nvidia graphics (HDMI), 1GB RAM,
a 32GB SSD or a large capacity HDD, and all the USB and other ports you could possibly
want”) are hardly the heavy-metal monsters we used to think about when discussing
“servers”, and yet still serve the purpose. If we don’t need the server for its processing
power, and if we don’t need it for its central location (as a rendezvous point for
clients to discover each other and/or centralize data), then what purpose does the
server serve?
&lt;/p&gt;
&lt;p&gt;
Maybe it’s time to take a really hard look again into those peer-to-peer ideas from
about a half-decade ago.
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=42807b50-d3ec-4147-8015-e3198ee8b186" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
 <pubDate>Wed, 25 Jan 2012 15:45:33 -0800</pubDate>
</item>
<item>
 <title>Ted Neward: Is Programming Less Exciting Today?</title>
 <link>http://blogs.tedneward.com/2012/01/25/Is+Programming+Less+Exciting+Today.aspx</link>
 <description>&lt;p&gt;
As discriminatory as this is going to sound, this one is for the old-timers. If you
started programming after the turn of the milennium, I don’t know if you’re going
to be able to follow the trend of this post—not out of any serious deficiency on your
part, hardly that. But I think this is something only the old-timers are going to
identify with. (And thus, do I alienate probably 80% of my readership, but so be it.)
&lt;/p&gt;
&lt;p&gt;
Is it me, or is programming just less interesting today than it was two decades ago?
&lt;/p&gt;
&lt;p&gt;
By all means, shake your smartphones and other mobile devices at me and say, “Dude,
how can you say that?”, but in many ways programming for Android and iOS reminds me
of programming for Windows and Mac OS two decades ago. HTML 5 and JavaScript remind
me of ten years ago, the first time HTML and JavaScript came around. The discussions
around programming languages remind me of the discussions around C++. The discussions
around NoSQL remind me of the arguments both for and against relational databases.
It all feels like we’ve been here before, with only the names having changed.
&lt;/p&gt;
&lt;p&gt;
Don’t get me wrong—if any of you comment on the differences between HTML 5 now and
HTML 3.2 then, or the degree of the various browser companies agreeing to the standard
today against the “browser wars” of a decade ago, I’ll agree with you. This isn’t
so much of a rational and logical discussion as it is an emotive and intuitive one.
It just &lt;em&gt;feels&lt;/em&gt; similar.
&lt;/p&gt;
&lt;p&gt;
To be honest, I get this sense that across the entire industry right now, there’s
a sort of malaise, a general sort of “Bah, nothing really all that new is going on
anymore”. NoSQL is re-introducing storage ideas that had been around before but were
discarded (perhaps injudiciously and too quickly) in favor of the relational model.
Functional languages have obviously been in place since the 50’s (in Lisp). And so
on.
&lt;/p&gt;
&lt;p&gt;
More importantly, look at the Java community: what truly innovative ideas have emerged
here in the last five years? Every new open-source project or commercial endeavor
either seems to be a refinement of an idea before it (how many different times are
we going to create a new Web framework, guys?) or an attempt to leverage an idea coming
from somewhere else (be it from .NET or from Ruby or from JavaScript or….). With the
upcoming .NET 4.5 release and Windows 8, Microsoft is holding out very little “new
and exciting” bits for the community to invest emotionally in: we hear about “async”
in C# 5 (something that F# has had already, thank you), and of course there is WinRT
(another platform or virtual machine… sort of), and… well, honestly, didn’t we just
do this a decade ago? Where is the WCFs, the WPFs, the Silverlights, the things that
would get us fired up? Hell, even a new approach to data access might stir some excitement.
Node.js feels like an attempt to reinvent the app server, but if you look back far
enough you see that the app server itself was reinvented once (in the Java world)
in Spring and other lightweight frameworks, and before that by people who actually
thought to write their own web servers in straight Java. (And, for the record, the
whole event-driven I/O thing is something that’s been done in both Java and .NET a
long time before now.)
&lt;/p&gt;
&lt;p&gt;
And as much as this is going to probably just throw fat on the fire, all the excitement
around JavaScript as a language reminds me of the excitement about Ruby as a language.
Does nobody remember that Sun did this once already, with Phobos? Or that Netscape
did this with LiveScript? JavaScript on the server end is not new, folks. It’s just
new to the people who’d never seen it before.
&lt;/p&gt;
&lt;p&gt;
In years past, there has always seemed to be something deeper, something more exciting
and more innovative that drives the industry in strange ways. Artificial Intelligence
was one such thing: the search to try and bring computers to a state of human-like
sentience drove a lot of interesting ideas and concepts forward, but over the last
decade or two, AI seems to have lost almost all of its luster and momentum. User interfaces—specifically,
GUIs—were another force for a while, until GUIs got to the point where they were so
common and so deeply rooted in their chosen pasts (the single-button of the Mac, the
menubar-per-window of Windows, etc) that they left themselves so little room for maneuver.
At least this is one area where Microsoft is (maybe) putting the fatted sacred cow
to the butcher’s knife, with their Metro UI moves in Windows 8… but only up to a point.
&lt;/p&gt;
&lt;p&gt;
Maybe I’m just old and tired and should hang up my keyboard and go take up farming,
then go retire to my front porch’s rocking chair and practice my &lt;em&gt;Hey you kids!
Getoffamylawn!&lt;/em&gt; or something. But before you dismiss me entirely, do me a favor
and tell me: what gets you excited these days? If you’ve been programming for twenty
years, what about the industry today gets your blood moving and your mind sharpened?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.tedneward.com/aggbug.ashx?id=20604d47-a520-4a9f-8fd2-469caa49eb40" /&gt;
&lt;br /&gt;
&lt;hr /&gt;
Enterprise consulting, mentoring or instruction. Java, C++, .NET or XML services.
1-day or multi-day workshops available. &lt;a href="mailto:ted@tedneward.com"&gt;Contact
me for details&lt;/a&gt;.</description>
 <pubDate>Wed, 25 Jan 2012 15:24:43 -0800</pubDate>
</item>
</channel>
</rss>

