<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[]]></title>
  <link href="http://rywalker.com/atom.xml" rel="self"/>
  <link href="http://rywalker.com/"/>
  <updated>2012-03-21T11:27:42-04:00</updated>
  <id>http://rywalker.com/</id>
  <author>
    <name><![CDATA[Ry Walker]]></name>
    <email><![CDATA[ry@rywalker.com]]></email>
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Cincinnati Ruby Developers discuss Laura Baverman's article on Cincinnati tech talent]]></title>
    <link href="http://rywalker.com/cincinnati-ruby-developers-discuss-laura-bavermans-article-on-cincinnati-tech-talent/"/>
    <updated>2012-03-21T00:00:00-04:00</updated>
    <id>http://rywalker.com/cincinnati-ruby-developers-discuss-laura-bavermans-article-on-cincinnati-tech-talent</id>
    <content type="html"><![CDATA[<p>On March 17th, Joe Herbers <a href="https://groups.google.com/d/topic/cincinnatirb/2QNxBiNj2IY/discussion">posted</a> a link to Laura Baverman&#8217;s <a href="http://enterchange.cincinnati.com/2012/03/11/talent-main/">article</a> on Cincinnati.com&#8217;s Enter Change blog. On Tuesday, March 21st, approximately twenty Ruby developers gathered for our monthly <a href="http://cincinnati.rb">Cincinnati.rb</a> meeting to discuss some of the points of the article.</p>

<!-- more -->


<h2>The discussion</h2>

<p>The room discussed everything from lean startups, doing a startup with venture investment, working for large businesses, working for medium- and small-businesses, and the difference between &#8220;working at a startup&#8221; vs. &#8220;being an entrepreneur&#8221;.</p>

<p>I went in with an agenda: I love the idea that developers should team up and funnel their &#8220;excess passion&#8221; into side projects, taking no outside investment, and growing these projects enough to allow them to quit their day jobs eventually.</p>

<p>My friend from the Brandery, <a href="https://twitter.com/#!/daveknox">Dave Knox</a>, asked me to share their <a href="http://brandery.org/brandsmith/">&#8220;Brandsmith&#8221;</a> concept that they&#8217;re rolling out to help get more developers involved at the Brandery this summer. The response from the room of successful developers was quite unanimous: none of the experienced developers in the room would be interested in an arrangement to work full-time for four months for $5,000 for the upcoming Brandery class.</p>

<p>The group showed a conservative side in several areas:</p>

<ul>
<li>Many aren&#8217;t really interested in taking a career risk by joining a startup for sweat equity. Angel &amp; early-stage VC funded environments don&#8217;t promote good work/life balance, which experienced developers with families value greatly. Even though corporate jobs can be frustrating at times - working with people who don&#8217;t care very much, or aren&#8217;t highly skilled, the steady paycheck is compelling.</li>
<li>Some, including me, were against the entire concept of accepting outside investment, instead favoring ideas that can be executed with spare time, inline with <a href="https://twitter.com/#!/dhh">DHH</a>&#8217;s <a href="http://37signals.com/svn/posts/2874-the-problem-with-the-tech-worlds-swing-for-the-fences-approach">distaste for &#8220;swing for the fences&#8221; business models</a>.</li>
<li>Some, including <a href="http://gaslightsoftware.com/">Gaslight Software</a> co-founder <a href="https://twitter.com/#!/dougalcorn">Doug Alcorn</a> are comfortable consulting and the risk of finding clients versus the make or break of a single product.</li>
<li><a href="https://twitter.com/#!/agilious">Bill Barnett</a>, another Gaslight Software co-founder, advocated the less than developer friendly idea of heavy marketing first to vette the business idea and follow with minimal development. Once you have a market tested idea, you then invest in the functionality demanded by your customers.</li>
</ul>


<p>However, some of the meeting attendees are working for startups now, where they work with people who are excited and energetic.</p>

<p>After listening to the room, <a href="https://twitter.com/#!/krohrbaugh">Kevin Rohrbaugh</a> took a stance that, based on what he heard, if he was going to do a startup, he&#8217;d probably do it in the Bay Area, because the likihood of finding a smart co-founder is greater there. I took the stance that I&#8217;d do it in Cincinnati, because there are not dominant companies like Google, Apple, and hundreds of others with which to battle for top talent.</p>

<p>A big consensus at the end was that the members of the Cincinnati Ruby Brigade really value community. Working and learning from a small team where their opinions get heard, where they can work with people who are better than them that they can learn from. And the typical incubator startup in Cincinnati doesn&#8217;t seem to provide this sort of opportunity.</p>

<h2>My answer</h2>

<p>Ruby developers are spoiled, in a good way. Our language and development practices are centered on developer happiness. When our code is bad, we call it a &#8220;code smell&#8221;. When our work environment is bad, we view that as a &#8220;work smell&#8221; and will not tolerate it for long. Life is too short.</p>

<p>Cincinnati needs more of our experienced developers to start successful web product companies where we can create a work enviroment that works for us. These companies would grow into a core group of companies that will attract talent, serve as a role model for startups, and prove that it can be done in Cincinnati. These developer-founders will create developer-friendly work environments, focusing on product quality and customer service (let&#8217;s call it the Apple model) over marketing and salesmanship. A recent article on Forbes.com supports my answer &#8211; <a href="http://www.forbes.com/sites/venkateshrao/2012/03/09/great-ceos-must-be-either-technical-or-financial/">Great CEOs Must be Either Technical or Financial</a>.</p>

<p>I also think it&#8217;s important for everyone in the startup to dabble in all aspects of the business, to create a better understanding of the work others are doing. In other words, &#8220;idea guys&#8221; should spend time to learn HTML. The developers should man the customer support queue and talk to prospective customers.</p>

<p>We need companies where young Rails developers can get a couple of years of real-world experience in a good work environemnt, then split off and do their own thing, creating a greater demand for technical talent.</p>

<h2>What&#8217;s next?</h2>

<p>I&#8217;m grateful for the efforts that CincyTech, Brandery, and other startup-oriented groups have made. They are moving the needle in the right direction.</p>

<p>The members of the Cincinnati Ruby Brigade looks forward to ongoing engagement with the creative &amp; marketing communities on these issues, for the benefit of everyone involved in the Cincinnati web tech industry.</p>

<ul>
<li>The upcoming <a href="http://qcmerge.com/">QCMerge</a> web conference can provide a forum where an expert panel can discuss these issues. I would thoroughly enjoy sitting on the panel. &#8220;If you think can&#8217;t start a web-based business  here in Cincy, I challenge to you come to QCMerge.&#8221;</li>
<li>We invite <a href="http://www.laurabaverman.com/">Laura Baverman</a> to continue digging into these issues. Let&#8217;s setup some time to get opinionated people on these subjects together to further the discussions.</li>
<li>The developers of Cincinnati.rb should lead by example, and practice what we preach. We will pull together a &#8220;mastermind&#8221; subgroup to discuss product ideas, and spend time actually building stuff rather than talking and doing <a href="http://codekata.pragprog.com/">code katas</a> :)</li>
<li>Brandery is a great start, but it isn&#8217;t enough. It&#8217;s focused on investment-seeking B2C and B2B2C models. There are huge opportunities in B2B and SaaS business models, as well as unfunded &#8220;bootstrap&#8221; efforts.</li>
<li>We need more success stories in the Cincinnati tech startup scene to inspire and attract developers.</li>
<li>Everyone with core skills (marketing, creative, technical) needs to recognize when they are taking non-productive attitudes towards their non-primary communities. It takes expertise in all areas of business to be successful.</li>
</ul>


<h2>Can Cincinnati be a tech hub?</h2>

<p>Are we pigeon-holed as a &#8220;marketing&#8221; and &#8220;branding&#8221; city? Can we make the leap to becoming a legitimate, respected &#8220;tech&#8221; startup town? In some ways we&#8217;re trailing smaller markets in Ohio, such as the <a href="http://www.ybi.org/">Youngstown Business Incubator</a> which has a strong portfolio of growing tech companies, and 300 people working on a downtown campus that forms a nucleus for growth.</p>

<h2>The future: software shortage</h2>

<p>I listened recently to <a href="http://5by5.tv/webahead/19">an episode of &#8220;The Web Ahead&#8221; with Jen Simmons</a> where she talked with <a href="https://twitter.com/#!/lukew">Luke Wroblewski</a> about the future of the web. Citing the rapid growth of mobile, and the fact that more than 50% of adults in the U.S. now have a computer in their pocket, that over the next five years the demand for software will explode, and that every company is becoming more and more a software company.</p>

<p>Software developers, especially those in emerging languages, are in a very good position.</p>

<p>Ultimately, I agree with the conclusion of the article, that the market for smart developers willing to work for sweat equity in Cincinnati has far more demand than supply. Even with focused effort, there are numerous forces that may cause the situation to get worse, rather than better.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Experimenting with Backbone.js]]></title>
    <link href="http://rywalker.com/experimenting-with-backbonejs/"/>
    <updated>2012-01-01T00:00:00-05:00</updated>
    <id>http://rywalker.com/experimenting-with-backbonejs</id>
    <content type="html"><![CDATA[<p>This experiment uses:</p>

<ul>
<li>Ruby 1.9.2p0</li>
<li>Rails 3.0.1</li>
<li>Backbone.js 0.2.0</li>
<li>jQuery 1.4.3</li>
</ul>


<!-- more -->


<h2>Start a new project</h2>

<pre><code>rvm use 1.9.2
cd Documents/work
rails new backbone-crm
cd backbone-crm/
rm public/javascripts/*
curl -L http://code.jquery.com/jquery-1.4.3.min.js &gt; public/javascripts/jquery.js
curl -L http://www.json.org/json2.js &gt; public/javascripts/json2.js
curl -L http://documentcloud.github.com/underscore/underscore-min.js &gt; public/javascripts/underscore.js
curl -L http://documentcloud.github.com/backbone/backbone.js &gt; public/javascripts/backbone.js
</code></pre>

<h2>Ensure you&#8217;re setup</h2>

<p>Delete the index.html and replace with this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="cp">&lt;!DOCTYPE html&gt;</span>
</span><span class='line'><span class="nt">&lt;html&gt;</span>
</span><span class='line'>  <span class="nt">&lt;head&gt;</span>
</span><span class='line'>    <span class="nt">&lt;title&gt;</span>Backbone test<span class="nt">&lt;/title&gt;</span>
</span><span class='line'>    <span class="nt">&lt;meta</span> <span class="na">http-equiv=</span><span class="s">&quot;content-type&quot;</span> <span class="na">content=</span><span class="s">&quot;text/html;charset=UTF-8&quot;</span> <span class="nt">/&gt;</span>
</span><span class='line'>    <span class="nt">&lt;meta</span> <span class="na">http-equiv=</span><span class="s">&quot;X-UA-Compatible&quot;</span> <span class="na">content=</span><span class="s">&quot;chrome=1&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>
</span><span class='line'>    <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;/javascripts/jquery.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
</span><span class='line'>    <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;/javascripts/json2.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
</span><span class='line'>    <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;/javascripts/underscore.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
</span><span class='line'>    <span class="nt">&lt;script </span><span class="na">src=</span><span class="s">&quot;/javascripts/backbone.js&quot;</span><span class="nt">&gt;&lt;/script&gt;</span>
</span><span class='line'>    <span class="nt">&lt;script </span><span class="na">type=</span><span class="s">&quot;text/javascript&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>      <span class="kd">var</span> <span class="nx">object</span> <span class="o">=</span> <span class="p">{};</span>
</span><span class='line'>
</span><span class='line'>      <span class="nx">_</span><span class="p">.</span><span class="nx">extend</span><span class="p">(</span><span class="nx">object</span><span class="p">,</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">Events</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>      <span class="nx">object</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="s2">&quot;alert&quot;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">msg</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="nx">alert</span><span class="p">(</span><span class="s2">&quot;Triggered &quot;</span> <span class="o">+</span> <span class="nx">msg</span><span class="p">);</span>
</span><span class='line'>      <span class="p">});</span>
</span><span class='line'>
</span><span class='line'>      <span class="nx">object</span><span class="p">.</span><span class="nx">trigger</span><span class="p">(</span><span class="s2">&quot;alert&quot;</span><span class="p">,</span> <span class="s2">&quot;an event&quot;</span><span class="p">);</span>
</span><span class='line'>    <span class="nt">&lt;/script&gt;</span>
</span><span class='line'>  <span class="nt">&lt;/head&gt;</span>
</span><span class='line'>  <span class="nt">&lt;body&gt;</span>
</span><span class='line'>    <span class="nt">&lt;h1&gt;</span>Backbone CMS<span class="nt">&lt;/h1&gt;</span>
</span><span class='line'>  <span class="nt">&lt;/body&gt;</span>
</span><span class='line'><span class="nt">&lt;/html&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>We are simply creating an empty object, extending it with Backbone.Events, bind an event called &#8220;alert&#8221; to it, then trigger that event. Not too exciting, but we are up and running with Backbone.js.</p>

<p>But that doesn&#8217;t help us build an app. So let&#8217;s nuke that code, but first, let&#8217;s get the contacts resource built.</p>

<pre><code>rails generate resource Contact first_name:string last_name:string email:string
rake db:migrate
</code></pre>

<p>Fill out the controller:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">ContactsController</span> <span class="o">&lt;</span> <span class="no">ApplicationController</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">respond_to</span> <span class="ss">:json</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">create</span>
</span><span class='line'>    <span class="n">attributes</span> <span class="o">=</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">JSON</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="n">params</span><span class="o">[</span><span class="ss">:model</span><span class="o">]</span><span class="p">)</span>
</span><span class='line'>    <span class="vi">@contact</span> <span class="o">=</span> <span class="no">Contact</span><span class="o">.</span><span class="n">create</span><span class="p">(</span><span class="n">attributes</span><span class="p">)</span>
</span><span class='line'>    <span class="n">respond_with</span><span class="p">(</span><span class="vi">@contact</span><span class="p">,</span> <span class="ss">:location</span> <span class="o">=&gt;</span> <span class="n">contacts_url</span><span class="p">)</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>And then let&#8217;s switch out the javascript on the index.html with this:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="o">&lt;</span><span class="nx">script</span> <span class="nx">type</span><span class="o">=</span><span class="s2">&quot;text/javascript&quot;</span><span class="o">&gt;</span>
</span><span class='line'>
</span><span class='line'><span class="nx">$</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
</span><span class='line'>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">Contacts</span> <span class="o">=</span> <span class="nx">Backbone</span><span class="p">.</span><span class="nx">Collection</span><span class="p">.</span><span class="nx">extend</span><span class="p">({</span>
</span><span class='line'>    <span class="nx">url</span><span class="o">:</span> <span class="s1">&#39;/contacts&#39;</span>
</span><span class='line'>  <span class="p">});</span>
</span><span class='line'>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">contacts</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Contacts</span><span class="p">();</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">contacts</span><span class="p">.</span><span class="nx">create</span><span class="p">({</span>
</span><span class='line'>    <span class="nx">first_name</span><span class="o">:</span> <span class="s2">&quot;John&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="nx">last_name</span><span class="o">:</span> <span class="s2">&quot;Doe&quot;</span>
</span><span class='line'>  <span class="p">});</span>
</span><span class='line'>
</span><span class='line'><span class="p">});</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="err">/script&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Reload the page, and open up Firebug and you&#8217;ll see the message got through to the Rails controller, and check the database, the data should be there.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Lean Startup Book Notes]]></title>
    <link href="http://rywalker.com/lean-startup-notes/"/>
    <updated>2011-10-10T00:00:00-04:00</updated>
    <id>http://rywalker.com/lean-startup-notes</id>
    <content type="html"><![CDATA[<p><a href="http://www.amazon.com/Lean-Startup-Entrepreneurs-Continuous-Innovation/dp/0307887898">Lean Startup</a> is a great book by Eric Ries, highly recommended.</p>

<!-- more -->


<h2>Five Principles</h2>

<ul>
<li>Entrepreneurs are everywhere&mdash;not just in startups, big companies need them too.</li>
<li>Entrepreneurship is management&mdash;you&#8217;re building an organization in an environment of extreme uncertainty.</li>
<li>Validated learning&mdash;the primary reason for existence for a startup is to learn. The best way to do that is through scientific experiments that test each element of the vision.</li>
<li>Build-measure-learn&mdash;ideas are built into products which are measured generating data that we learn from and form new ideas, including whether to pivot or persevere. Through this loop learning informs the vision, and vision drives the learning.</li>
<li>Innovation accounting&mdash;establish the baseline, tune the engine, pivot or perservere. Cohort analysis is important concept here, because you don&#8217;t get fooled by the snowball effect of traditional metrics. Good metrics need to be actionable, accessible, and auditable. Use A/B split testing once the baseline is established to improve the ratios.</li>
</ul>


<h2>Key insights</h2>

<ul>
<li>Any work that generating value (providing benefit to the customer) is waste. In the context of a startup, any work that isn&#8217;t directly linked to a learning experiment is waste.</li>
<li>The two most important assumptions entrepreneurs make are the value hypothesis and the growth hypothesis.

<ul>
<li>Value: will the product or service really deliver value?</li>
<li>Growth: how will customers find the product or service?</li>
</ul>
</li>
<li>Concierge MVP&mdash;operate the product with people doing the work that computers will eventually do, to test the viability of the whole concept before building a lot of software.</li>
<li>An experiment is a product. And first products should not be built to be perfect. Their role is to generate data that we can learn from.</li>
<li>Learn the difference between dangerous vanity metrics vs. nuts-and-bolts actionable metrics.</li>
<li>Keep batches small&mdash;strive to keep delivery as close to continuous as possible.</li>
</ul>


<h2>Four questions before starting something</h2>

<ul>
<li>Do customers recognize they have the problem we&#8217;re trying to solve?</li>
<li>If there was a solution, would they buy it?</li>
<li>Would they buy it from us?</li>
<li>Can we build a solution to that problem? (The common tendency is to jump right to this one.)</li>
</ul>


<h2>Types of pivots</h2>

<ul>
<li>Zoom-in Pivot&mdash;a single feature becomes the product.</li>
<li>Zoom-out Pivot&mdash;what was considered the whole product becomes a single feature of a larger product.</li>
<li>Customer Segment Pivot&mdash;the product solves problems for a different customer than originally conceived.</li>
<li>Customer Need Pivot&mdash;we learn about the customer, and that they have bigger problems that we can solve, which may require tweaks to the product or perhaps a different product altogether.</li>
<li>Platform Pivot&mdash;change from an application to a platform or vice versa.</li>
<li>Business Architecture Pivot&mdash;switch from high volume, low margin to low volume, high margin, or the reverse.</li>
<li>Value Capture Pivot&mdash;changes to revenue or monitization model.</li>
<li>Engine of Growth Pivot&mdash;change in growth strategy: viral, sticky, paid.</li>
<li>Channel Pivot&mdash;change in sales or distribution, where or how it&#8217;s sold or bought.</li>
<li>Technology Pivot&mdash;change to capture superior cost and/or performance.</li>
</ul>


<h2>Four primary ways past customers drive our growth</h2>

<ul>
<li>Word of mouth</li>
<li>As a side effect of product usage&mdash;others see the customer using the product.</li>
<li>Funded advertising</li>
<li>Repeat purchase or use</li>
</ul>


<h2>Three engines of growth</h2>

<ul>
<li>Sticky&mdash;product is addicting to use.</li>
<li>Viral&mdash;people tell people about it.</li>
<li>Paid&mdash;buy ads that generate customer acquisition.</li>
</ul>


<h2>How to nurture disruptive innovation</h2>

<ul>
<li>Provide scarce but secure resources</li>
<li>Give independent development authority</li>
<li>Embed a personal stake in the outcome</li>
<li>Protect the parent organization if it&#8217;s not used to an experimental culture</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Google Prediction API First Looks]]></title>
    <link href="http://rywalker.com/google-prediction-api-first-looks/"/>
    <updated>2011-04-24T00:00:00-04:00</updated>
    <id>http://rywalker.com/google-prediction-api-first-looks</id>
    <content type="html"><![CDATA[<p>Sitting around on a Sunday night, decided to finally take a little dive on something that&#8217;s had my eye for a while, the <a href="http://code.google.com/apis/predict/">Google Prediction API</a>.</p>

<!-- more -->


<h2>Signup</h2>

<p><img src="http://code.google.com/apis/predict/images/predictionapi-128.png" class="right"></p>

<ol>
<li>Visited <a href="https://code.google.com/apis/console">the Google APIs console</a> and turned on the Google Prediction API.</li>
<li>Needed to <a href="https://spreadsheets.google.com/a/google.com/viewform?hl=en&formkey=dEhTS1AydGxMbC1IRGZPOFJGdnRSeHc6MQ#gid=0">sign up for Google Storage account</a> - this seemed discouraging, since it was a Google Docs waiting list, and I figured I&#8217;d be dead in the water tonight, maybe waiting forever. I wrote as persuasive an application as I could :)</li>
<li>I noticed that they metioned they were going to turn on billing in early 2011, pricing was only $10/month. From the console, there was a &#8220;billing&#8221; link that I could enable. So I decided to enable billing, hoping that would help with Google Storage account issue.</li>
<li>Checking my email, I had already been emailed a Google Storage invite. Not sure if it was automatic or my application caught their eye (I suspect the former) but the hurdle was jumped. Woot!</li>
</ol>


<h2>Hello Prediction</h2>

<p>I followed the <a href="http://code.google.com/apis/predict/docs/hello_world.html">hello world tutorial</a> that Google provides. I won&#8217;t cut-and-paste all the steps, since the tutorial is well-written, but here are some notes from the process.</p>

<p>I needed to install <code>gsutil</code> - pretty easy; <a href="http://code.google.com/apis/storage/docs/gsutil.html#install">instructions here</a>.</p>

<p>I needed to <a href="https://sandbox.google.com/storage/m/manage">create a Google Storage access key</a>.</p>

<p>Can&#8217;t use bucket &#8216;examplebucket&#8217;. I used &#8216;play-prediction&#8217; and it allowed me to create bucket and then I copied the file up using <code>gsutil cp ./language_id.txt gs://play-prediction/prediction_models/languages</code>.</p>

<p>Save your Google API Access Key (found on the <a href="https://code.google.com/apis/console/">API Console</a> through the &#8220;API Access&#8221; link on the left, at the bottom of the page &#8220;Simple API Access&#8221;, to file <code>googlekey</code>.</p>

<p>I copied <code>oauth-train.sh</code>, <code>oauth-check-training.sh</code>, and <code>oauth-predict.sh</code> to my local project folder, and <code>chmod 755</code> on the to make them executable.</p>

<p>I was able to train using <code>./oauth-train.sh play-prediction/prediction_models/languages</code> command.</p>

<p><code>./oauth-check-training.sh play-prediction/prediction_models/languages</code> yielded the expected result, training accuracy was 0.95.</p>

<p><code>./oauth-predict.sh play-prediction/prediction_models/languages "\"Sitting around on a Sunday night, decided to finally take a little dive on something that’s had my eye for a while, the Google Prediction API.\""</code> was interpreted as English correctly.</p>

<p><code>./oauth-predict.sh play-prediction/prediction_models/languages "\"El sol se levantará mañana y quién sabe lo que traerá la marea?\""</code> was interpreted as Spanish correctly.</p>

<p><code>./oauth-predict.sh play-prediction/prediction_models/languages "\"La gloire est éphémère, mais l'obscurité est éternelle.\""</code> was interpreted as French correctly.</p>

<p>I noticed the engine didn&#8217;t perform as well on short phrases, to be expected.</p>

<h2>Closing</h2>

<p>Very cool system, took me about an hour to get through the tutorial.</p>

<p>Mission accomplished, Google Prediction API is much less abstract in my mind now.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The invisible forces that shape us]]></title>
    <link href="http://rywalker.com/the-invisible-forces-that-shapes-us/"/>
    <updated>2011-04-08T00:00:00-04:00</updated>
    <id>http://rywalker.com/the-invisible-forces-that-shapes-us</id>
    <content type="html"><![CDATA[<p>At all times, there are two forces tugging on us&#8230;</p>

<!-- more -->


<ul>
<li>The current moment, including our current emotional and physical state.</li>
<li>Our long term view of the world, which shapes what things mean to us.</li>
</ul>


<p>If we bring this tug-of-war into our active conciousness, we can focus ourselves to towards the achievement of our goals.</p>

<p>We are making three decisions every moment of our life:</p>

<ul>
<li>What am I going to focus on? On the past? The present? The future? Myself? Others?</li>
<li>What does it mean? Is it the end? Is it the beginning? Is it punishment? Is it a reward?</li>
<li>What am I going to do? Give up? Move forward?</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Moving Rails 3 and MongoDB app to Heroku]]></title>
    <link href="http://rywalker.com/moving-rails-3-and-mongo-db-app-to-heroku/"/>
    <updated>2010-12-29T00:00:00-05:00</updated>
    <id>http://rywalker.com/moving-rails-3-and-mongo-db-app-to-heroku</id>
    <content type="html"><![CDATA[<p>It seemed on the surface so easy&mdash;I figured it&#8217;d take 20-30 minutes. Ended up taking 1.5 hrs, not too horrible.</p>

<!-- more -->


<h2>Add Heroku</h2>

<p>First I <code>cd</code> to the project, which is already using git &amp; github.</p>

<pre><code>heroku create --stack bamboo-mri-1.9.2
heroku addons:add mongohq:free
</code></pre>

<h2>Cleanup gems from beta to release</h2>

<p>Cleaned up my Gemfile:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">source</span> <span class="s2">&quot;http://rubygems.org&quot;</span>
</span><span class='line'><span class="n">source</span> <span class="s2">&quot;http://gems.github.com&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="n">gem</span> <span class="s2">&quot;rails&quot;</span>
</span><span class='line'><span class="n">gem</span> <span class="s2">&quot;bson_ext&quot;</span>
</span><span class='line'><span class="n">gem</span> <span class="s2">&quot;mongo_mapper&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="n">gem</span> <span class="s2">&quot;haml&quot;</span><span class="p">,</span> <span class="s2">&quot;~&gt; 3.0.2&quot;</span>
</span><span class='line'><span class="n">gem</span> <span class="s2">&quot;compass&quot;</span><span class="p">,</span> <span class="s2">&quot; ~&gt; 0.10.0&quot;</span><span class="p">,</span> <span class="ss">:require</span> <span class="o">=&gt;</span> <span class="kp">false</span>
</span></code></pre></td></tr></table></div></figure>


<h2>App errored because of Heroku read only file system</h2>

<p>Googled around, found <a href="http://lds.li/post/673242899/compass-with-rails-3-on-heroku">this post</a> which had a straightforward workaround. I had a static stylesheet related to jquery-ui in my /stylesheets directory, so after some trial and error, I ended up modifying /config/compass.rb:</p>

<pre><code>css_dir = "tmp/stylesheets/compiled"
</code></pre>

<p>and added this file: config/initializers/stylesheets.rb</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="s1">&#39;fileutils&#39;</span>
</span><span class='line'><span class="no">FileUtils</span><span class="o">.</span><span class="n">mkdir_p</span><span class="p">(</span><span class="no">Rails</span><span class="o">.</span><span class="n">root</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s2">&quot;tmp&quot;</span><span class="p">,</span> <span class="s2">&quot;stylesheets&quot;</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="no">Sass</span><span class="o">::</span><span class="no">Plugin</span><span class="o">.</span><span class="n">on_updating_stylesheet</span> <span class="k">do</span> <span class="o">|</span><span class="n">template</span><span class="p">,</span> <span class="n">css</span><span class="o">|</span>
</span><span class='line'>  <span class="nb">puts</span> <span class="s2">&quot;Compiling </span><span class="si">#{</span><span class="n">template</span><span class="si">}</span><span class="s2"> to </span><span class="si">#{</span><span class="n">css</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="no">Rails</span><span class="o">.</span><span class="n">configuration</span><span class="o">.</span><span class="n">middleware</span><span class="o">.</span><span class="n">insert_before</span><span class="p">(</span>
</span><span class='line'>  <span class="s1">&#39;Rack::Sendfile&#39;</span><span class="p">,</span> <span class="s1">&#39;Rack::Static&#39;</span><span class="p">,</span>
</span><span class='line'>  <span class="ss">:urls</span> <span class="o">=&gt;</span> <span class="o">[</span><span class="s1">&#39;/stylesheets/compiled&#39;</span><span class="o">]</span><span class="p">,</span>
</span><span class='line'>  <span class="ss">:root</span> <span class="o">=&gt;</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="no">Rails</span><span class="o">.</span><span class="n">root</span><span class="si">}</span><span class="s2">/tmp&quot;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>I also had some cleanup due to a change in format of <code>box-shadow</code> in Compass.</p>

<h2>Add custom domain</h2>

<p>Finally I just needed to switchover the DNS, and add custom domain to heroku:</p>

<pre><code>heroku addons:add custom_domains
heroku domains:add incentimove.com
</code></pre>

<p>All done, and I get to shut down what was supposed to be a short-lived $30/mo. Linode VPS :)</p>

<p>Thanks <a href="http://lds.li/">Lincoln</a> for your helpful blog post and to <a href="http://heroku.com">Heroku</a> and <a href="https://mongohq.com">MongoHQ</a> for your kick ass products.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Making Statistical Social Validation Fast]]></title>
    <link href="http://rywalker.com/making-statistical-social-validation-fast/"/>
    <updated>2010-12-27T00:00:00-05:00</updated>
    <id>http://rywalker.com/making-statistical-social-validation-fast</id>
    <content type="html"><![CDATA[<p>One of the challenges we have at RecruitMilitary is that there is a perception that there are lots of companies out there that &#8220;prey on veterans&#8221; and there is skepticism that we are who we say we are.</p>

<!-- more -->


<h2>Why do it?</h2>

<p>We know we&#8217;re for real, but how do we communicate that quickly and effectively?</p>

<p>I&#8217;ve been pushing us to just show the numbers&#8230; while we&#8217;re always pushing for improvement, on the whole I&#8217;m proud of our activity and <a href="http://recruitmilitary.com">just showing visitors our numbers in real time</a>, I believe, should be convincing. Here&#8217;s a screenshot of the finished product:</p>

<p><img src="http://rywalker.com/assets/recruitmilitary_board_social_validation.png" title="RecruitMilitary Board Social Validation" alt="RecruitMilitary Board Social Validation" /></p>

<p>You can <a href="http://recruitmilitary.com">visit the site</a> (during business hours is best) to see the stats bar in action.</p>

<h2>The technical nitty-gritty</h2>

<p>We knew that we&#8217;d end up with people sitting and watching the stats increment, so we wanted to make sure the request was fast. We use <a href="https://github.com/defunkt/resque">Resque</a> as our background processing system, and along with it came <a href="http://redis.io/">Redis</a>. We basically took the ideas in <a href="https://github.com/defunkt/resque/blob/master/lib/resque/stat.rb">Resque&#8217;s stat module</a> and implemented a very fast way to get the counters from our system.</p>

<p>However, the data is actually coming from a different Rails app than our marketing site, so we rolled a simple little jsonp service. Here&#8217;s the controller:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">module</span> <span class="nn">Api::V1</span>
</span><span class='line'>  <span class="k">class</span> <span class="nc">StatsController</span> <span class="o">&lt;</span> <span class="no">BaseController</span>
</span><span class='line'>    <span class="n">caches_action</span> <span class="ss">:index</span><span class="p">,</span> <span class="ss">:expires_in</span> <span class="o">=&gt;</span> <span class="mi">10</span><span class="o">.</span><span class="n">seconds</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">def</span> <span class="nf">index</span>
</span><span class='line'>      <span class="vi">@stats</span> <span class="o">=</span> <span class="no">Board</span><span class="o">::</span><span class="no">Stat</span><span class="o">::</span><span class="no">DAILY_STATS</span><span class="o">.</span><span class="n">inject</span><span class="p">({})</span> <span class="k">do</span> <span class="o">|</span><span class="n">h</span><span class="p">,</span> <span class="n">stat</span><span class="o">|</span>
</span><span class='line'>        <span class="n">h</span><span class="o">[</span><span class="n">stat</span><span class="o">]</span> <span class="o">=</span> <span class="no">Board</span><span class="o">::</span><span class="no">Stat</span><span class="o">[</span><span class="n">stat</span><span class="o">]</span>
</span><span class='line'>        <span class="n">h</span><span class="o">[</span><span class="s2">&quot;</span><span class="si">#{</span><span class="n">stat</span><span class="si">}</span><span class="s2">_today&quot;</span><span class="o">]</span> <span class="o">=</span> <span class="no">Board</span><span class="o">::</span><span class="no">Stat</span><span class="o">[</span><span class="s2">&quot;</span><span class="si">#{</span><span class="n">stat</span><span class="si">}</span><span class="s2">_today&quot;</span><span class="o">]</span>
</span><span class='line'>        <span class="n">h</span>
</span><span class='line'>      <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>      <span class="n">render_json</span><span class="p">(</span><span class="vi">@stats</span><span class="p">)</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>In the destination page, we drop in a simple div that is filled in with javascript:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">&quot;stats&quot;</span> <span class="na">class=</span><span class="s">&quot;hidden wide bordered&quot;</span><span class="nt">&gt;</span>
</span><span class='line'><span class="nt">&lt;/div&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>The controller response was quick, but we were getting so many hits to it, we had to optimize further.</p>

<p>We did two 2 things:</p>

<ul>
<li>Define an explicit <code>jsonpCallback</code> property. It turned out that the way we had jsonp setup, it was generating a unique callback string with each request in the URL, effectively nullifying our cache of 10 seconds.</li>
<li>We found that requests were happing around the clock, people were leaving our page up in a browser window. A quick check on <code>($("html").is(".blurred"))</code> did the trick&mdash;we stopped updating the stats if the browser window wasn&#8217;t active.</li>
</ul>


<p>The refined javascript:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
<span class='line-number'>105</span>
</pre></td><td class='code'><pre><code class='javascript'><span class='line'><span class="nx">$</span><span class="p">.</span><span class="nx">fn</span><span class="p">.</span><span class="nx">boardStatisticize</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="kd">var</span> <span class="nx">stat_box</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
</span><span class='line'>    <span class="nx">cache</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
</span><span class='line'>    <span class="nx">dataType</span><span class="o">:</span> <span class="s2">&quot;jsonp&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="nx">jsonpCallback</span><span class="o">:</span> <span class="s2">&quot;statsicizer&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="nx">success</span><span class="o">:</span> <span class="nx">handleResponse</span><span class="p">,</span>
</span><span class='line'>    <span class="nx">url</span><span class="o">:</span> <span class="s2">&quot;https://board.recruitmilitary.com/api/v1/stats&quot;</span>
</span><span class='line'>  <span class="p">});</span>
</span><span class='line'>
</span><span class='line'>  <span class="kd">function</span> <span class="nx">handleResponse</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">var</span> <span class="nx">stats</span> <span class="o">=</span> <span class="nx">data</span><span class="p">;</span>
</span><span class='line'>    <span class="kd">var</span> <span class="nx">displayed_stats</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;active_jobs&quot;</span><span class="p">,</span> <span class="s2">&quot;job_views&quot;</span><span class="p">,</span>
</span><span class='line'>      <span class="s2">&quot;candidate_accounts&quot;</span><span class="p">,</span> <span class="s2">&quot;candidate_profile_views&quot;</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">for</span> <span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">displayed_stats</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">insertStat</span><span class="p">(</span><span class="nx">displayed_stats</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span> <span class="nx">stats</span><span class="p">[</span><span class="nx">displayed_stats</span><span class="p">[</span><span class="nx">i</span><span class="p">]]);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">function</span> <span class="nx">insertStat</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;&lt;div&gt;&lt;/div&gt;&quot;</span><span class="p">)</span>
</span><span class='line'>        <span class="p">.</span><span class="nx">addClass</span><span class="p">(</span><span class="s2">&quot;block&quot;</span><span class="p">)</span>
</span><span class='line'>        <span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="nx">blockLabel</span><span class="p">())</span>
</span><span class='line'>        <span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="nx">totalCount</span><span class="p">())</span>
</span><span class='line'>        <span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="nx">todayCount</span><span class="p">())</span>
</span><span class='line'>        <span class="p">.</span><span class="nx">attr</span><span class="p">(</span><span class="s2">&quot;id&quot;</span><span class="p">,</span> <span class="nx">key</span><span class="p">)</span>
</span><span class='line'>        <span class="p">.</span><span class="nx">css</span><span class="p">(</span><span class="s2">&quot;width&quot;</span><span class="p">,</span> <span class="p">(</span><span class="nx">stat_box</span><span class="p">.</span><span class="nx">innerWidth</span><span class="p">()</span> <span class="o">/</span> <span class="mi">4</span><span class="p">)</span> <span class="o">-</span> <span class="mi">22</span><span class="p">)</span>
</span><span class='line'>        <span class="p">.</span><span class="nx">appendTo</span><span class="p">(</span><span class="nx">stat_box</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>      <span class="kd">function</span> <span class="nx">blockLabel</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;&lt;h3&gt;&lt;/h3&gt;&quot;</span><span class="p">)</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">addClass</span><span class="p">(</span><span class="s2">&quot;label&quot;</span><span class="p">)</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">text</span><span class="p">(</span><span class="nx">BR</span><span class="p">.</span><span class="nx">board_stat_labels</span><span class="p">[</span><span class="nx">key</span><span class="p">]);</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>      <span class="kd">function</span> <span class="nx">totalCount</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;&lt;span&gt;&lt;/span&gt;&quot;</span><span class="p">)</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">addClass</span><span class="p">(</span><span class="s2">&quot;total-count&quot;</span><span class="p">)</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">data</span><span class="p">(</span><span class="s2">&quot;count&quot;</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">text</span><span class="p">(</span><span class="nx">commafyNumber</span><span class="p">(</span><span class="nx">value</span><span class="p">));</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>      <span class="kd">function</span> <span class="nx">todayCount</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>        <span class="k">return</span> <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;&lt;span&gt;&lt;/span&gt;&quot;</span><span class="p">)</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">addClass</span><span class="p">(</span><span class="s2">&quot;today-count&quot;</span><span class="p">)</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">data</span><span class="p">(</span><span class="s2">&quot;count&quot;</span><span class="p">,</span> <span class="nx">stats</span><span class="p">[</span><span class="nx">key</span> <span class="o">+</span> <span class="s2">&quot;_today&quot;</span><span class="p">])</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">text</span><span class="p">(</span><span class="s2">&quot;+&quot;</span> <span class="o">+</span> <span class="nx">commafyNumber</span><span class="p">(</span><span class="nx">stats</span><span class="p">[</span><span class="nx">key</span> <span class="o">+</span> <span class="s2">&quot;_today&quot;</span><span class="p">])</span> <span class="o">+</span> <span class="s2">&quot; today&quot;</span><span class="p">);</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#candidate-form .job-count&quot;</span><span class="p">)</span>
</span><span class='line'>      <span class="p">.</span><span class="nx">text</span><span class="p">(</span><span class="nx">commafyNumber</span><span class="p">(</span><span class="nx">stats</span><span class="p">[</span><span class="s2">&quot;active_jobs&quot;</span><span class="p">]));</span>
</span><span class='line'>
</span><span class='line'>    <span class="nx">stat_box</span><span class="p">.</span><span class="nx">removeClass</span><span class="p">(</span><span class="s2">&quot;hidden&quot;</span><span class="p">);</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>  <span class="nb">window</span><span class="p">.</span><span class="nx">setInterval</span><span class="p">(</span><span class="s2">&quot;updateBoardStats()&quot;</span><span class="p">,</span> <span class="mi">10000</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="k">this</span><span class="p">;</span>
</span><span class='line'><span class="p">};</span>
</span><span class='line'>
</span><span class='line'><span class="kd">function</span> <span class="nx">updateBoardStats</span><span class="p">()</span> <span class="p">{</span>
</span><span class='line'>  <span class="k">if</span> <span class="p">(</span><span class="nx">$</span><span class="p">(</span><span class="s2">&quot;html&quot;</span><span class="p">).</span><span class="nx">is</span><span class="p">(</span><span class="s2">&quot;.blurred&quot;</span><span class="p">))</span>
</span><span class='line'>    <span class="k">return</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>  <span class="nx">$</span><span class="p">.</span><span class="nx">ajax</span><span class="p">({</span>
</span><span class='line'>    <span class="nx">cache</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
</span><span class='line'>    <span class="nx">dataType</span><span class="o">:</span> <span class="s2">&quot;jsonp&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="nx">jsonpCallback</span><span class="o">:</span> <span class="s2">&quot;statsicizer&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="nx">success</span><span class="o">:</span> <span class="nx">handleResponse</span><span class="p">,</span>
</span><span class='line'>    <span class="nx">url</span><span class="o">:</span> <span class="s2">&quot;https://board.recruitmilitary.com/api/v1/stats&quot;</span>
</span><span class='line'>  <span class="p">});</span>
</span><span class='line'>
</span><span class='line'>  <span class="kd">function</span> <span class="nx">handleResponse</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>    <span class="kd">var</span> <span class="nx">stats</span> <span class="o">=</span> <span class="nx">data</span><span class="p">;</span>
</span><span class='line'>    <span class="kd">var</span> <span class="nx">displayed_stats</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;active_jobs&quot;</span><span class="p">,</span> <span class="s2">&quot;job_views&quot;</span><span class="p">,</span>
</span><span class='line'>      <span class="s2">&quot;candidate_accounts&quot;</span><span class="p">,</span> <span class="s2">&quot;candidate_profile_views&quot;</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>    <span class="k">for</span> <span class="p">(</span><span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">displayed_stats</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="nx">updateStat</span><span class="p">(</span><span class="nx">displayed_stats</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span> <span class="nx">stats</span><span class="p">[</span><span class="nx">displayed_stats</span><span class="p">[</span><span class="nx">i</span><span class="p">]]);</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="kd">function</span> <span class="nx">updateStat</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>      <span class="kd">var</span> <span class="nx">total</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#&quot;</span> <span class="o">+</span> <span class="nx">key</span> <span class="o">+</span> <span class="s2">&quot; .total-count&quot;</span><span class="p">);</span>
</span><span class='line'>      <span class="kd">var</span> <span class="nx">today</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#&quot;</span> <span class="o">+</span> <span class="nx">key</span> <span class="o">+</span> <span class="s2">&quot; .today-count&quot;</span><span class="p">);</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">if</span> <span class="p">(</span><span class="nx">total</span><span class="p">.</span><span class="nx">data</span><span class="p">(</span><span class="s2">&quot;count&quot;</span><span class="p">)</span> <span class="o">!==</span> <span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
</span><span class='line'>        <span class="nx">total</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">addClass</span><span class="p">(</span><span class="s2">&quot;updated&quot;</span><span class="p">)</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">data</span><span class="p">(</span><span class="s2">&quot;count&quot;</span><span class="p">,</span> <span class="nx">value</span><span class="p">)</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">text</span><span class="p">(</span><span class="nx">commafyNumber</span><span class="p">(</span><span class="nx">value</span><span class="p">))</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">switchClass</span><span class="p">(</span><span class="s2">&quot;updated&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="mi">5000</span><span class="p">);</span>
</span><span class='line'>        <span class="nx">today</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">addClass</span><span class="p">(</span><span class="s2">&quot;updated&quot;</span><span class="p">)</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">data</span><span class="p">(</span><span class="s2">&quot;count&quot;</span><span class="p">,</span> <span class="nx">stats</span><span class="p">[</span><span class="nx">key</span> <span class="o">+</span> <span class="s2">&quot;_today&quot;</span><span class="p">])</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">text</span><span class="p">(</span><span class="s2">&quot;+&quot;</span> <span class="o">+</span> <span class="nx">commafyNumber</span><span class="p">(</span><span class="nx">stats</span><span class="p">[</span><span class="nx">key</span> <span class="o">+</span> <span class="s2">&quot;_today&quot;</span><span class="p">])</span> <span class="o">+</span> <span class="s2">&quot; today&quot;</span><span class="p">)</span>
</span><span class='line'>          <span class="p">.</span><span class="nx">switchClass</span><span class="p">(</span><span class="s2">&quot;updated&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="mi">5000</span><span class="p">);</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>    <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>    <span class="nx">$</span><span class="p">(</span><span class="s2">&quot;#candidate-form .job-count&quot;</span><span class="p">)</span>
</span><span class='line'>      <span class="p">.</span><span class="nx">text</span><span class="p">(</span><span class="nx">commafyNumber</span><span class="p">(</span><span class="nx">stats</span><span class="p">[</span><span class="s2">&quot;active_jobs&quot;</span><span class="p">]));</span>
</span><span class='line'>  <span class="p">}</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>Great work from <a href="http://diminishing.org/">Michael</a> and <a href="http://jasonspeck.com/">Jason</a> on this, we continue to get daily complements on our new home page, and I know this feature is central to the great experience.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Great email from Get Satisfaction]]></title>
    <link href="http://rywalker.com/great_email_from_get_satisfaction/"/>
    <updated>2010-12-26T00:00:00-05:00</updated>
    <id>http://rywalker.com/great_email_from_get_satisfaction</id>
    <content type="html"><![CDATA[<p>I&#8217;m a big fan of using statistical social validation in marketing&mdash;it&#8217;s a central concept in all our redesign of RecruitMilitary web applications.</p>

<!-- more -->


<p>One of the managers @ RecruitMilitary forwarded me a <a href="http://rywalker.com/assets/get_satisfaction_email.png">great sample</a> from Get Satisfaction&#8230;</p>

<p><img src="http://rywalker.com/assets/get_satisfaction_email.png" title="Get Satisfaction Email" alt="Get Satisfaction Email" /></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[InsideSales.com Product Review]]></title>
    <link href="http://rywalker.com/insidesales-product-review/"/>
    <updated>2010-06-04T00:00:00-04:00</updated>
    <id>http://rywalker.com/insidesales-product-review</id>
    <content type="html"><![CDATA[<h2>Overview</h2>

<p>Insidesales.com CRM is a very ambitious product. It has a LOT of functionality. Unfortunately it&#8217;s got too many flaws for me to recommend it. I&#8217;m posting this review, as a current customer, as incentive for them to improve the product, in particular, my issues with it.</p>

<!-- more -->


<h2>Sales Process</h2>

<p>Their sales process was impeccable, and the rep we got was very sharp and helpful (thank you, Ben!). Not too pushy, let us evaluate on our own time.</p>

<p>I was a little bit concerned by the apparent lack of polish on the app, but assumed the internals were strong, that they just didn&#8217;t have a &#8220;great&#8221; UI design lead, which I can forgive. The price was significantly lower than Salesforce, so I let it go.</p>

<p>We knew we&#8217;d be heavy user of SOAP API, we reviewed docs and had some concerns there, but not enough to kill the deal.</p>

<h2>Implementation</h2>

<p>Weaknesses in the software begin to manifest.</p>

<ul>
<li>Lead import would occasionally lock the entire server (reps on phone affected.) They did respond quickly to resolve this, but it really shouldn&#8217;t be allowed to happen.</li>
<li>We were given API docs for 2.0, SOAP endpoints for 1.6, documentation was very sparse. Once we finally figured that out (I had to get sales rep back involved to give me a contact that could understand our problem.) Once we got 2.0 endpoints, the code was untested, we had at least a half-dozen back and forths trying to just get the API to work as advertised. This cost us weeks.</li>
<li>Training was weak, and after toying around with the product for a few weeks I actually corrected the trainer about how converting leads to Account/Contact works.</li>
</ul>


<h2>Production - Current State</h2>

<p><strong> Note: I&#8217;ll adjust this section as new issues are uncovered and old issues resolved </strong></p>

<h3>Pros:</h3>

<ul>
<li>Dialer works - our sales reps are more productive.</li>
<li>Dialer initiatives are very flexible and work great.</li>
<li>Total talk time reports are very good management tools.</li>
<li>Support team is responsive.</li>
</ul>


<h3>Cons:</h3>

<h4>Support:</h4>

<ul>
<li>Support tickets disappear from our UI when they resolve them, and we can&#8217;t see progress on tickets. I&#8217;d love to see them move to an off-the-shelf support system like Tender or ZenDesk, losing their homegrown system.</li>
<li>Support team&#8217;s technical knowledge doesn&#8217;t go very deep, and I had to go outside the process to get my urgent API issues worked on. Support has acknowledged that their exposure to API issues is limited, but I&#8217;d like to see a smooth escalation process on their end for these issues.</li>
</ul>


<h4>Accounts:</h4>

<ul>
<li>Duplicate accounts cannot be merged! Contacts have to be moved manually. (Even though there is a &#8220;Merge Accounts&#8221; button.)</li>
<li>A user asking &#8220;sales administrator&#8221; can&#8217;t convert leads without it changing them to the owner. We have significant cleanup to do after import, we&#8217;ll have to login as each user to avoid extra steps.</li>
<li>Can&#8217;t convert a lead that has an existing account without duplicating the account.</li>
</ul>


<h4>Mass email:</h4>

<ul>
<li>Mass email process is a bit backwards - must create a template then can email all contacts in an account, but it doesn&#8217;t provide any verification that the content merged in well before saying &#8220;OK, scheduled to send.&#8221;</li>
<li>I couldn&#8217;t find anywhere to see a list of send jobs pending or completed.</li>
</ul>


<h4>General:</h4>

<ul>
<li>URLs are not canonical - when looking at a lead URL is something like https://recruitmilitary.insidesales.com/leads/lead?itemOffset=0 where it should be https://recruitmilitary.insidesales.com/leads/{id} - something that can be cut and pasted + shared</li>
<li>App is somewhat ugly - lots of different font sizes, kludgy UI in spots</li>
<li>Application is optimized for Internet Explorer; some things don&#8217;t work in Firefox

<ul>
<li>Pages don&#8217;t fit the browser - bottom scrollbar often when doesn&#8217;t need to be there (maybe Firefox only)</li>
<li>Form designer barely works in Firefox</li>
</ul>
</li>
</ul>


<h4>API &amp; Import:</h4>

<ul>
<li>SOAP API is very basic, not all objects fully implemented (for example, can&#8217;t import product details for a deal)</li>
<li>Report (summarized) data not available in API</li>
<li>API returns deleted LEAD records, no way to filter them out. We had to ask for a purge of test data.</li>
<li>Account/contact import is broken, we had to import hundreds of thousands of records through individual SOAP API interactions.</li>
</ul>


<h4>Reports:</h4>

<ul>
<li>Reports present data that contradicts other reports.</li>
<li>There is a beta reporting system pasted in there, but not cohesive with other report lists.</li>
</ul>


<h4>JabberDog:</h4>

<ul>
<li>Can&#8217;t archive past JabberDog jobs, so the dropdown continues to grow and grow.</li>
</ul>


<h4>Updates:</h4>

<ul>
<li>In April 2011, I had a nice call with Ken Krogue regarding this blog post, and his committment to doing what it takes to win us over and convert this blog post to a positive review. I look forward to that journey, it will help both of our businesses in the long run. More to come :)</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Manager Developer Syndrome]]></title>
    <link href="http://rywalker.com/manager-developer-syndrome/"/>
    <updated>2010-04-22T00:00:00-04:00</updated>
    <id>http://rywalker.com/manager-developer-syndrome</id>
    <content type="html"><![CDATA[<p>Manager Developer Syndrome (&#8220;MDS&#8221;) is a condition where a manager/developer has a tough time writing quality code because he has become short-term focused due to prolonged exposure to managerial environments and conditions.</p>

<!-- more -->


<h2>What causes Manager Developer Syndrome?</h2>

<p>It starts with prolonged experience to the concerns of management, such as generating cash for payroll, pursuing hot deals, and taking care of important customers.</p>

<p>The individual is then exposed to the awesomeness of outside-in BDD/TDD testing methodology and tools, and a world where seemingly thousands of developers on Github who are &#8220;doing it the right way&#8221;, flaunting their excellent work in plain sight.</p>

<p>This combination of factors triggers the realization that the individual sucks and should do something about it.</p>

<h2>What are the symptoms?</h2>

<ul>
<li>Not refactoring. Without tests, it&#8217;s deemed just too dangerous and not enough short-term ROI. Plus there are a million other things to do, including checking your email, since it probably has accumulated 40+ emails since you decided to spend a few hours focusing on code.</li>
<li>Not releasing code publicly. It&#8217;s not tested. No one will use it if it&#8217;s not tested.</li>
<li>Making commits on group projects late at night, when hopefully no one is looking.</li>
</ul>


<h2>How is it treated?</h2>

<ul>
<li>Stop the bullshit excuses, and just invest the time to finally REALLY learn and use RSpec.</li>
<li>Start contributing to open source projects, even if it&#8217;s just helping to improve documentation.</li>
<li>Stop adding new implementation code without tests, even in projects where there are no specs presently.</li>
<li>Bonus points: Stop using TextMate and learn to use a real editor (VIM or Emacs).</li>
</ul>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Easy canonical URLs in Apache]]></title>
    <link href="http://rywalker.com/easy-canonical-urls-in-apache/"/>
    <updated>2010-03-22T00:00:00-04:00</updated>
    <id>http://rywalker.com/easy-canonical-urls-in-apache</id>
    <content type="html"><![CDATA[<p>Eliminate duplicate URLs, not because of mythological duplicate content penalties, but for the sake of orderliness.</p>

<!-- more -->


<p>This domain was previously pointed to <a href="http://rywalker.mp">http://rywalker.mp</a>; Google now has old www.rywalker.com references from that era. It&#8217;s bugging me, so I want to try to clear it up in the future by having a no-www canonical URLs for this site.</p>

<p>Before:</p>

<pre><code>&lt;VirtualHost *:80&gt;
  ServerName rywalker.com
  ServerAlias www.rywalker.com
  DocumentRoot /home/deploy/apps/rywalker/nesta/public
&lt;/VirtualHost&gt;
</code></pre>

<p>During my research, I discovered that there is a <a href="http://www.seogeneration.co.uk/duplicate-content-myth/">duplicate content myth</a> circulating, and I did wonder if Google would love me more if I wasn&#8217;t tossing duplicate content out there with my server alias.</p>

<p>After:</p>

<pre><code>&lt;VirtualHost *:80&gt;
  ServerName rywalker.com
  DocumentRoot /home/deploy/apps/rywalker/nesta/public
&lt;/VirtualHost&gt;

&lt;VirtualHost *:80&gt;
  ServerName www.rywalker.com
  RedirectMatch 301 ^(.*)$ http://rywalker.com$1
&lt;/VirtualHost&gt;
</code></pre>

<p>Simple enough, hopefully my clarity goes rewarded by our search engine overlords. And if nothing else, I&#8217;ll be happy to see the www.rywalker.com references disappear from search results over time.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Use presenters and helpers for clean views]]></title>
    <link href="http://rywalker.com/use-presenters-and-helpers-for-clean-views/"/>
    <updated>2010-03-21T00:00:00-04:00</updated>
    <id>http://rywalker.com/use-presenters-and-helpers-for-clean-views</id>
    <content type="html"><![CDATA[<p>On complex pages, you can use the presenter pattern and Rails helper system to simplify your views so you can actually read them.</p>

<!-- more -->


<p>I&#8217;m working on this view:</p>

<p><img src="http://rywalker.com/assets/candidate_my_profile_screenshot.png" alt="Screenshot of My Profile in Job board project" /></p>

<p>Since we&#8217;re trying to encourage registration, I want to show certain fields, even if the user hasn&#8217;t filled out the information yet, to encourage them to complete the profile.</p>

<p>Here&#8217;s how a view may look without presentation pattern or helpers:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="o">&lt;</span><span class="n">ul</span> <span class="n">class</span><span class="o">=</span><span class="s2">&quot;contact-information&quot;</span><span class="o">&gt;</span>
</span><span class='line'>  <span class="o">&lt;</span><span class="n">li</span> <span class="n">class</span><span class="o">=</span><span class="s2">&quot;name&quot;</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="o">&lt;</span><span class="n">label</span><span class="o">&gt;</span><span class="no">Name</span><span class="o">&lt;</span><span class="sr">/label&gt;</span>
</span><span class='line'><span class="sr">    &lt;b&gt;&lt;%= @candidate.name %&gt;&lt;/</span><span class="n">b</span><span class="o">&gt;</span>
</span><span class='line'>  <span class="o">&lt;</span><span class="sr">/li&gt;</span>
</span><span class='line'><span class="sr">  &lt;li class=&quot;phone&quot;&gt;</span>
</span><span class='line'><span class="sr">    &lt;label&gt;Phone&lt;/</span><span class="n">label</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="o">&lt;</span><span class="n">b</span><span class="o">&gt;&lt;</span><span class="sx">%= @candidate.phone ? @candidate.phone : &quot;Not provided&quot; %&gt;&lt;/b&gt;</span>
</span><span class='line'><span class="sx">  &lt;/li&gt;</span>
</span><span class='line'><span class="sx">  &lt;li class=</span><span class="s2">&quot;work-interests&quot;</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="o">&lt;</span><span class="n">label</span><span class="o">&gt;</span><span class="no">Work</span> <span class="no">Interests</span><span class="o">&lt;</span><span class="sr">/label&gt;</span>
</span><span class='line'><span class="sr">    &lt;b&gt;&lt;%=</span>
</span><span class='line'><span class="sr">      if @candidate.work_interests</span>
</span><span class='line'><span class="sr">        @candidate.work_interests.map { |wi| wi.name }.join &quot;, &quot;)</span>
</span><span class='line'><span class="sr">      else</span>
</span><span class='line'><span class="sr">        &quot;None selected&quot;</span>
</span><span class='line'><span class="sr">      end %&gt;&lt;/</span><span class="n">b</span><span class="o">&gt;</span>
</span><span class='line'>  <span class="o">&lt;</span><span class="sr">/li&gt;</span>
</span><span class='line'><span class="sr">&lt;/u</span><span class="n">l</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Here&#8217;s what it can look like with them:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='html'><span class='line'><span class="nt">&lt;ul</span> <span class="na">class=</span><span class="s">&quot;contact-information&quot;</span><span class="nt">&gt;</span>
</span><span class='line'>  <span class="err">&lt;</span>%= profile_detail &quot;Name&quot;, @candidate.name %&gt;
</span><span class='line'>  <span class="err">&lt;</span>%= profile_detail &quot;Phone&quot;, @candidate.phone_text %&gt;
</span><span class='line'>  <span class="err">&lt;</span>%= profile_detail &quot;Work Interests&quot;, @candidate.work_interest_names %&gt;
</span><span class='line'><span class="nt">&lt;/ul&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Presenter code:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">class</span> <span class="nc">CandidatePresenter</span> <span class="o">&lt;</span> <span class="no">CachingPresenter</span>
</span><span class='line'>  <span class="n">presents</span> <span class="ss">:candidate</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">phone_text</span>
</span><span class='line'>    <span class="k">return</span> <span class="s2">&quot;Not provided&quot;</span> <span class="k">if</span> <span class="vi">@candidate</span><span class="o">.</span><span class="n">phone</span><span class="o">.</span><span class="n">blank?</span>
</span><span class='line'>    <span class="vi">@candidate</span><span class="o">.</span><span class="n">phone</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">future_work_interests_names</span>
</span><span class='line'>    <span class="k">return</span> <span class="s2">&quot;None selected&quot;</span> <span class="k">if</span> <span class="vi">@candidate</span><span class="o">.</span><span class="n">future_work_interests</span><span class="o">.</span><span class="n">empty?</span>
</span><span class='line'>    <span class="vi">@candidate</span><span class="o">.</span><span class="n">future_work_interests</span><span class="o">.</span><span class="n">map</span> <span class="p">{</span> <span class="o">|</span><span class="n">fwi</span><span class="o">|</span> <span class="n">fwi</span><span class="o">.</span><span class="n">name</span> <span class="p">}</span><span class="o">.</span><span class="n">join</span> <span class="s2">&quot;, &quot;</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Yes, you could build these presentation methods into the model, but that really clutters up the model. Yes, one more layer in the stack, but tossing this sort of stuff into the model really clutters it up, and <a href="http://www.engineyard.com/blog/2010/let-them-code-cake/">ActiveRecord is already doing perhaps too much</a>.</p>

<p>Helper code:</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">module</span> <span class="nn">CandidateDashboardHelper</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">profile_detail</span><span class="p">(</span><span class="n">label</span><span class="p">,</span><span class="n">value</span><span class="p">)</span>
</span><span class='line'>    <span class="k">return</span> <span class="k">if</span> <span class="n">value</span><span class="o">.</span><span class="n">blank?</span> <span class="o">||</span> <span class="n">label</span><span class="o">.</span><span class="n">blank?</span>
</span><span class='line'>    <span class="s2">&quot;&lt;li class=</span><span class="se">\&quot;</span><span class="si">#{</span><span class="n">label</span><span class="o">.</span><span class="n">downcase</span><span class="o">.</span><span class="n">dasherize</span><span class="si">}</span><span class="se">\&quot;</span><span class="s2">&gt;&lt;label&gt;</span><span class="si">#{</span><span class="n">label</span><span class="si">}</span><span class="s2">&lt;/label&gt;&lt;b&gt;</span><span class="si">#{</span><span class="n">value</span><span class="si">}</span><span class="s2">&lt;/b&gt;&lt;/li&gt;&quot;</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>The libary we&#8217;re leveraging is <a href="http://github.com/mhs/caching_presenter">Mutually Human&#8217;s fork of Zach Dennis&#8217;s Caching Presenter</a>. (Hi Mark, Zach, Craig, and John!)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Chaos 2010]]></title>
    <link href="http://rywalker.com/chaos-2010/"/>
    <updated>2010-03-16T00:00:00-04:00</updated>
    <id>http://rywalker.com/chaos-2010</id>
    <content type="html"><![CDATA[<p>What do you do when you have a rigid, monolithic app written in an outdated technology? You have no choice but to embrace chaos&#8230;</p>

<!-- more -->


<p>Yesterday I gave an hour talk at our company&#8217;s annual meeting, where I described how we&#8217;re going to tear down our monolithic legacy ASP app and replace over the next few months. In the afternoon, after thinking it through, I decided to name the collection of projects &#8220;Chaos 2010&#8221;.</p>

<p>In order to install <a href="http://insidesales.com">a call center solution</a> we need to replace our current phone system, so that&#8217;s project #1. InsideSales.com also has a CRM system that&#8217;s better than our homegrown system, so we&#8217;ll toss out that old system for all our sales team.</p>

<p>Problem is that breaks other parts of the monolithic legacy app, so we have to quickly follow that up with email marketing system work, accounting switchover from quickbooks offline to quickbooks online, launching our new job board product, building a new event management system, and then finally rebuilding all of our custom dashboard/reports that we have.</p>

<p>The current system has this structure:</p>

<p><img src="http://rywalker.com/assets/chaos_2010_current.png" alt="Chaos 2010 Current" /></p>

<p>The final system should look something like this:</p>

<p><img src="http://rywalker.com/assets/chaos_2010_future.png" alt="Chaos 2010 Future" /></p>

<p>We are building a list of projects in Google docs (image intentionally downsized to obfuscate details).</p>

<p><img src="http://rywalker.com/assets/chaos_2010_projects.png" alt="Chaos 2010 Projects" /></p>

<p>Each column outlines at a high level what we need to do within that project, what that project fixes, what that project breaks, and finally a list of things that remain broken after the project is complete.</p>

<p>The first two projects basically break a ton of stuff, then it&#8217;s six projects to try to put it back together. The end result will be that the company is in much better shape for the expected growth when the economy kicks back in.</p>

<h2>Future Updates</h2>

<p>I&#8217;ll report back in after we complete each project of Chaos 2010 with observations what went well and what went poorly. Wish us luck!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[The Cucumber Rspec Cycle]]></title>
    <link href="http://rywalker.com/cucumber-rspec-cycle/"/>
    <updated>2009-12-13T00:00:00-05:00</updated>
    <id>http://rywalker.com/cucumber-rspec-cycle</id>
    <content type="html"><![CDATA[<p>Extracted from the Rspec book for future quick reference.</p>

<!-- more -->


<ol>
<li><p>Write new feature/scenario.
Autotest runs your features and finds pending
steps. It remembers those scenarios.</p></li>
<li><p>Define pending steps.
Each time you save, autotest reruns the pending
scenarios. Watch them turn red and blue.</p></li>
<li><p>Pick a red step. Write the spec which exercises
the (unwritten) implementation behind that step.
Autotest sees your new red spec and remembers it.</p></li>
<li><p>Work on implementing the spec. Each time you save,
autotest reruns the red spec. No need to run any
features until you&#8217;re done with this. Autotest
keeps you drilled down.</p></li>
<li><p>Finish implementing the spec. When the spec turns
green, you&#8217;re done! Autotest pops the stack and
reruns the scenarios you&#8217;re working on.</p></li>
<li><p>Repeat from Step 3 until your scenarios are all
green. Now that you&#8217;ve done a chunk of work,
Autotest pops the stack again and runs all your
specs to make sure nothing is broken.</p></li>
<li><p>Fix any unit-level regressions. Once your specs
are green and the scenarios you were working on
are running, Autotest runs your entire feature set.</p></li>
<li><p>Fix any integration-level regressions. Now your
features should all be green. Return to step 1.</p></li>
</ol>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Web project process]]></title>
    <link href="http://rywalker.com/web-project-process/"/>
    <updated>2009-10-27T00:00:00-04:00</updated>
    <id>http://rywalker.com/web-project-process</id>
    <content type="html"><![CDATA[<p>Below is a web project process that you can use to jump start any web
application or web site initiative. Even if you&#8217;re not technical, the
more you do of this before bringing in help, the better off you will be.
However, when you add a significant member to the team, I&#8217;d recommend
going back to step one to ensure everyone has had appropriate input into
the plan, which maximizes buy-in for the new team member.</p>

<!-- more -->


<h2>1. The Brain Dump</h2>

<h3>The Team</h3>

<p>You will find it best to gather at least one other person to get through
the brain dump quickly and effectively.</p>

<h3>The Media</h3>

<p>Start the process using paper index cards. There&#8217;s something
about paper that will help you move quickly and creatively through this
important first step.</p>

<h3>Roles</h3>

<p>Record all the roles for the users of the system.</p>

<h3>Actions &amp; tasks</h3>

<p>Note every action or task they may want to do, or that you may want them to do.</p>

<h3>Wrap up</h3>

<p>When complete, organize your cards into a prioritize list by role. So if
you have five roles identified, you should have five prioritized lists
of desired features/tasks/stories. Then toss the paper.</p>

<h2>2. Modeling &amp; User Stories</h2>

<p>Develop “Ubiquitous language” — Words that work for both the code implementation and conversations with the customer. This language is also important for the screens, which need sentences + verbs (not typical programmer screens, which have lots of function, but no explanation.)</p>

<p>Add a few sentences to describe each story—just enough information to serve as a token for a conversation that will take place closer to implementation.</p>

<h2>3. Implementation</h2>

<p>Using the prioritized list by role, do the top row. The most important
task for each identified role. This will encourage you to build a system
that acts as a &#8220;walking skeleton&#8221; for the rest of the system.</p>

<h3>Screens</h3>

<ul>
<li>Which screens - REST conventions can do a lot of work - what is the logical name of the noun-verb combination?</li>
<li>What&#8217;s on them - design from the inside out. Just the content without the outer frame of navigation. What matters to the user of the screen. What are they trying to do? Put in words what things they are trying to do on the screen, including the various paths they may take. (Don&#8217;t just assume the page should be a standard REST-template form.)</li>
<li>Be completely rational, &#8220;don&#8217;t make me think&#8221; - when I see the screen, I instantly know what to do with it, it&#8217;s easy to complete the task.</li>
<li>Least effective difference - give things visual priority, doing just enough to create the hierarchy.</li>
</ul>


<h3>Flows</h3>

<p>Think with actions, every action has 3 screens&#8230;</p>

<ul>
<li>How you get to it</li>
<li>How do you do it</li>
<li>What happens afterwards - how do i know it worked. What do i want to do next?</li>
</ul>


<h3>HTML &amp; Coding</h3>

<p>Hopefully you know how to do this :)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Notes from Ryan Singer's "UI First" Presentation]]></title>
    <link href="http://rywalker.com/notes-from-ryan-singers-ui-first-presentation/"/>
    <updated>2009-07-07T00:00:00-04:00</updated>
    <id>http://rywalker.com/notes-from-ryan-singers-ui-first-presentation</id>
    <content type="html"><![CDATA[<h2>MODELING</h2>

<ol>
<li>Begin with modeling</li>
<li>Screens need language.</li>
<li>Typical programmer screen:
Lot&#8217;s of function, no explanation. No verbs. No sentences.</li>
<li>Start with a model that works for both the implementation and the customer. &#8220;Ubiquitous language&#8221;</li>
</ol>


<h2>SCREENS</h2>

<ol>
<li>Which screens - REST conventions do a lot of work for us - what is the logical name of the noun-verb combination?</li>
<li>What&#8217;s on them - design from the inside out. Just the content without the outer frame of navigation. What matters to the user of the screen. What are they trying to do? Put in words what things they are trying to do on the screen, including the various paths they may take. (Don&#8217;t just assume the page should be a standard REST-template form.)</li>
<li>Visual style &amp; tricks - be completely rational, &#8220;don&#8217;t make me think&#8221; - when i see the screen, I instantly know what to do with it, it&#8217;s easy to complete the task.</li>
<li>Least effective difference - give things visual priority, doing just enough to create the hierarchy</li>
</ol>


<h2>FLOWS</h2>

<ol>
<li>Think with actions instead of screens</li>
<li>Every action has 3 screens:

<ul>
<li>How you get to it</li>
<li>How do you do it</li>
<li>What happens afterwards - how do i know it worked. What do i want to do next?</li>
</ul>
</li>
</ol>


<h2>TEMPLATES</h2>

<ol>
<li>No HTML in helpers</li>
<li>No clever builders</li>
<li>CSS/JS follow same REST-inspired naming conventions (action-specific blocks in each file)</li>
<li>Treat ERB like an image tag (i.e. small, maybe calling a helper, etc.)</li>
<li>Use helpers to reveal intention.</li>
</ol>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Micro-apps are the future]]></title>
    <link href="http://rywalker.com/micro-apps-are-the-future/"/>
    <updated>2009-03-01T00:00:00-05:00</updated>
    <id>http://rywalker.com/micro-apps-are-the-future</id>
    <content type="html"><![CDATA[<p>The future of web development will involve the development of micro-apps, rather than &#8220;monolithic&#8221; apps. This is a very good thing for business customers of smart web development companies, as it will decrease complexity, and therefore cost.</p>

<!-- more -->


<h2>GitHub</h2>

<p>GitHub makes it very easy for developers who don’t know each other, but have common problems to solve, to collaborate without communication (very low friction).</p>

<h2>Ruby on Rails</h2>

<p>Rails makes it possible to develop web apps w/ web services rapidly.</p>

<h2>Cloud Computing</h2>

<p>Companies like Heroku, Slicehost, Amazon EC2 are make it easier &amp; easier to deploy &amp; scale your infrastructure without needing hardware experts.</p>

<h2>SaaS</h2>

<p>Software as a Service has become mainstream &amp; acceptable, and it’s easy with tools like Spreedly or RailsKits to allow customers to buy without any sales involvement. Because Rails apps commonly have both web UI + web service APIs, these can be used as standalone apps or components of bigger apps.</p>

<p>If you build each component of your system in a decoupled way, you have built something that could potentially be developed out as a standalone project that could be either released as open source (and get developers around the world to debug/improve/expand it) or release it as a SaaS subscription product.</p>

<h2>The Catch</h2>

<p>The catch is that very few web developers are so close to the edge of this. If you&#8217;re starting from scratch, or aren&#8217;t afraid of the big rewrite, be sure to choose a partner that is using a lightweight dynamic language like Ruby or Python, and that uses open-source software behind the project. Any other choice, and you&#8217;re wasting your money.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[What is product management?]]></title>
    <link href="http://rywalker.com/what-is-product-management/"/>
    <updated>2009-01-11T00:00:00-05:00</updated>
    <id>http://rywalker.com/what-is-product-management</id>
    <content type="html"><![CDATA[<p>I was asked recently to share my thoughts on what the role of a product manager should be (related to B2B intangible services). It&#8217;s a complex subject.</p>

<!-- more -->


<p>Product management is about managing the experience cycle and building something that people will want to use.</p>

<h2>Experience Cycle</h2>

<p>DDO has <a href="http://www.dubberly.com/wp-content/uploads/2008/06/ddo_interactions_experiencecycle.pdf">a paper on what it calls the Experience Cycle</a>.</p>

<p>In a nutshell, I love the model, and I think it forms the core for what product managers should be focusing on.</p>

<ul>
<li>connect &amp; attract possible customers</li>
<li>orient them to the possibilities (i.e. product presentation, documentation, demos, trial account)</li>
<li>interact with the product/service, with a good experience as the outcome</li>
<li>extend &amp; retain, develop customer loyalty</li>
<li>help them become an advocate, communicating their satisfaction with other people</li>
</ul>


<p>They break down Apple at the end of the PDF, which has some of the best managed brands on the planet.</p>

<h2>Google Product Development Product</h2>

<p>Evelyn Rodriguez
<a href="http://evelynrodriguez.typepad.com/crossroads_dispatches/files/GoogleProductDevProcess.pdf">posted her notes</a> from a talk about how Google focuses on user-centered design, using small, agile teams (like startups) to develop ideas.</p>

<p>&#8220;If you build something users will use, there will be a way to make money.&#8221;</p>

<p>&#8220;Good quality, by itself, improves usage.&#8221;</p>

<ul>
<li>Build something that is valuable to people.</li>
<li>Monetize it (with separate monetization team)</li>
</ul>


<p>I think this Google stuff is very complimentary to the Experience Cycle content from DDO.</p>

<p>So my &#8220;short answer&#8221;, with evidence from two very successful brands I admire, is this:</p>

<p><b>&#8220;The essence of product management is designing, creating, improving, and monetizing customer journeys.&#8221;</b></p>

<h2>Great consultant-speak, but what about execution?</h2>

<p>For existing product, I think execution =</p>

<ul>
<li>Maintain or improve product quality (&amp; customer experience)</li>
<li>Monetization (attract customers, clearly communicate potential benefits of product usage, getting them to buy, keeping them happy &amp; getting them to renew, and hopefully getting them to talk about us in a positive way)</li>
</ul>


<p>We can change the language, to be less consultant-speak or put it in specific terms for our projects.</p>

<ul>
<li>Assign a small team (2-3 people) to manage the product/project. Don&#8217;t make the error of assigning one person solo. A small team helps ensure continuity of knowledge &amp; healthy peer pressure to perform.</li>
<li>Their mission: 1) ongoing monetization 2) improving customer experience.</li>
<li>How to accomplish the mission is up to them. They should feel free to find customers directly, or to try to sell product through the existing sales force &#8211; let them decide how to grow revenues and improve user experience,
with assistance from specialists &amp; executives, as requested.</li>
</ul>


<p>Of course, you have to have good people for it to work, of course, since each project acts as a mini-startup.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Products are never finished, only abandoned.]]></title>
    <link href="http://rywalker.com/products-are-never-finished-only-abandoned/"/>
    <updated>2008-12-31T00:00:00-05:00</updated>
    <id>http://rywalker.com/products-are-never-finished-only-abandoned</id>
    <content type="html"><![CDATA[<p>Business initiatives are a form of art, and project portfolios require gardening&#8230;</p>

<!-- more -->


<h2>Business Initiatives are a Form of Art</h2>

<p>Leonardo da Vinci
<img src="http://upload.wikimedia.org/wikipedia/commons/thumb/b/ba/Leonardo_self.jpg/220px-Leonardo_self.jpg" width="220" height="345" class="left"> once said &#8220;Art is never finished, only abandoned.&#8221;</p>

<p>Whenever we&#8217;re attempting to develop a new project, refine an existing product, reorganize a department, re-envision the brand (really any business initiative or project), execution requires significant creativity. <em>These sorts of projects, like art, are never finished, only abandoned.</em></p>

<p>You might be saying &#8220;no.&#8221; If we reorganize the department, the project can be called &#8220;done&#8221;, we can move on. I argue that if you analyze WHY you reorganized, you&#8217;ll uncover an underlying unachievable ideal. You reorganized the sales department because you wanted to MAXIMIZE THE EFFECTIVENESS OF YOUR SALESFORCE, an initiative that is perpetual.</p>

<p>You redesigned your website in order to IMPROVE CUSTOMER EXPERIENCE. An ideal that cannot ever be fully realized.</p>

<p>Very little project management software supports this worldview, that projects are never finished, only abandoned. <em>So I&#8217;ve been thinking about how software like that might work.</em></p>

<h2>Products are like Fireworks Shows</h2>

<p>Products are like fireworks shows. If you put on a good fireworks show, people expect you to do it bigger &amp; better next year. To meet their expectations, you need to plan an escalating annual budget.</p>

<p>Products should be work the same way. If you spent $50k on a product in 2008, plan to spend $75k in 2009, and $100k in 2010. Don&#8217;t fool yourself into thinking that there was some upfront investment in year 1, and that year 2 can require 1/2 the investment.</p>

<p>Yes you can skimp in year 2. However, your &#8220;fireworks&#8221; are not going to impress anyone&#8211;your audience will see that you cut your budget in 1/2. And YOU FAILED TO MAXIMIZING YOUR INITIAL INVESTMENT.</p>

<p>The metaphor is getting strange, and I know nothing about the real business of fireworks shows, <em>so I move on to a better metaphor&#8230;</em></p>

<h2>Project Portfolios Require Gardening</h2>

<p>Smart business people
<img src="http://i247.photobucket.com/albums/gg158/MDA2008/seedlings.jpg" width="240" height="180" class="left"> are charismatic and results-driven, and sit in leadership &amp; management roles. They tend to generating lots of great ideas. Let&#8217;s call these &#8220;seeds&#8221;.</p>

<p>They influence the organization to act on many ideas. Let&#8217;s call these germinating change initiatives &#8220;seedlings&#8221;. Taken individually, the idea was sound, the cost to get it started was low. It was a no-brainer to allocate resources to get started, to test out the idea a bit.</p>

<p>The problem is in aggregate. <em>The resources required to tend the rapidly growing garden greatly surpass the organization capacity.</em></p>

<p>It&#8217;s FUN and seems very productive to grow a seed into a seedling. Unfortunately, that&#8217;s where the problems start&#8230;</p>

<h2>The Overcrowded, Decaying Garden of Too Many Plants</h2>

<p><img src="http://www.ipm.iastate.edu/ipm/icm/2003/8-4-2003/dead_soy_plants.jpg" width="252" height="189" class="right">
The problem with
many small businesses is that we often plant many seeds, grow many fragile seedlings, and then don&#8217;t dedicate adequate resources to continue to nurture these seedlings into maturity. Creative executives move on to the &#8220;next great idea&#8221;.</p>

<p>The landscape becomes crowded. And important initiatives of yesterday are temporarily dropped in order to focus on germinating some new idea. Decay sets in. What can we do?</p>

<h2>See the Landscape</h2>

<p>The software would need to help expose the landscape. What investments has the organization made? What is the state of those investments? Which important initiatives are being underfed? What initiatives should be terminated? Which need to be be pruned or changed?</p>

<p><em>IS THIS A PROBLEM YOUR BUSINESS FACES?</em></p>

<p>I&#8217;m curious if this is a generally universal problem, or perhaps I&#8217;ve just been exposed to a subset of industry where this problem seems to be most pervasive (web software companies).</p>

<p>Perhaps ERP software covers this off? I&#8217;ve not been exposed to ERP software, nor have I seen anything tailored to Small- and Medium-Sized Businesses (the market segment that I&#8217;ve spent my career focused on.)</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[3 strikes, you're allowed the "big rewrite"]]></title>
    <link href="http://rywalker.com/3-strikes-to-the-big-rewrite/"/>
    <updated>2008-07-28T00:00:00-04:00</updated>
    <id>http://rywalker.com/3-strikes-to-the-big-rewrite</id>
    <content type="html"><![CDATA[<p>If your app passes any of the three tests, it may be worth
salvaging&mdash;3 strikes, it&#8217;s out.</p>

<!-- more -->


<h2>1. Spaghetti flows freely</h2>

<p>The codebase is large enough to require some refactoring, but very little of it has ever been done.</p>

<h2>2. Outdated platform</h2>

<p>The site is using outdated technology that no good
  developer really wants to touch anymore (i.e. Microsoft ASP,
  data-processing-centric Java, VB.NET, etc.)</p>

<h2>3. The experience sucks</h2>

<p>The site is ugly, hard-to-use, etc.</p>

<h2>Who is to blame?</h2>

<p>Who is to blame for an application to get to the point that it
needs tossed out the door? If resources were unreasonably
constrained by non-IT management against the recommendations made
by IT, then the non-IT management is to blame. However, if IT never
asked for additional resources to avoid the 3 strikes, then it must
take full responsibility for the impending death of a codebase.</p>
]]></content>
  </entry>
  
</feed>

