﻿<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:ng="http://newsgator.com/schema/extensions"><channel><title>My Clippings on NewsGator Online</title><link>http://www.newsgator.com</link><description>My Clippings on NewsGator Online</description><lastBuildDate>Fri, 04 Sep 2009 10:27:52 GMT</lastBuildDate><ttl>60</ttl><item><title>That's Not a Memory Leak, It's Bloat</title><link>http://www.engineyard.com/blog/2009/thats-not-a-memory-leak-its-bloat/</link><description>&lt;a href="http://news.ycombinator.com/item?id=803205"&gt;Comments&lt;/a&gt;</description><pubDate>Thu, 03 Sep 2009 19:46:03 GMT</pubDate><guid isPermaLink="false">tag:newsgator.com,2006:Feed.aspx/1269202/10442614710</guid><comments>http://news.ycombinator.com/item?id=803205</comments><source url="http://news.ycombinator.com/rss">Hacker News</source><ng:postId>10442614710</ng:postId><ng:feedId>1269202</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>Catch up or get left behind</title><link>http://feedproxy.google.com/~r/ryansholin/~3/e_xSLiaC_Go/</link><description>&lt;p&gt;I&amp;#8217;ve been a nomad for a few days in the middle of a short-by-my-standards 300+ mile move from the suburbs of Rochester, NY to the suburbs of Washington D.C. and boy are my legs tired.&lt;/p&gt;
&lt;p&gt;But I&amp;#8217;m catching up on my reading, and found a few things to share with you on the theme of catching up&amp;#8230;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://vimeo.com/6394721"&gt;VIDEO: Investing in Your Staff&lt;/a&gt;&lt;br /&gt;
&lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="286.875" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="src" value="http://vimeo.com/moogaloop.swf?clip_id=6394721&amp;amp;server=vimeo.com&amp;amp;show_title=0&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=00adef&amp;amp;fullscreen=1" /&gt;&lt;embed type="application/x-shockwave-flash" width="425" height="286.875" src="http://vimeo.com/moogaloop.swf?clip_id=6394721&amp;amp;server=vimeo.com&amp;amp;show_title=0&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=00adef&amp;amp;fullscreen=1" allowscriptaccess="always" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;
CoPress on Vimeo | September 2, 2009&lt;br /&gt;
The latest excellent video presentation from CoPress, making a case for innovation in your news organization.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.knightblog.org/2010-knight-news-challenge-is-now-open-for-business/"&gt;2010 Knight News Challenge is now open for business&lt;/a&gt;&lt;br /&gt;
&amp;#8220;Got a great idea for transforming the future of news? The 2010 Knight News Challenge is now accepting applications, through October 15th!&amp;#8221;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.niemanlab.org/2009/09/the-future-of-news-in-4-dimensions-charting-new-kinds-of-news-orgs/"&gt;The future of news in 4 dimensions: Charting new kinds of news orgs&lt;/a&gt;&lt;br /&gt;
Nieman Journalism Lab | September 1, 2009&lt;br /&gt;
C.W. Anderson builds the sort of continuum/quadrant chart that makes the mass communications scholar in me go all smiley.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://twitter.com/brianboyer/status/3717756612"&gt;brianboyer&lt;/a&gt;: If you&amp;#8217;re a Tribune reader, this&amp;#8217;ll make it nicer. RT  &lt;a title="Click here to view this profile on Twitter!" href="http://www.twitter.com/ryanmark"&gt;@ryanmark&lt;/a&gt;: Update to ChicagoTribune.com userstyle &lt;a title="Click here to view this link!" href="http://userstyles.org/styles/20347"&gt;http://userstyles.org/styles/20347&lt;/a&gt;&lt;br /&gt;
Twitter | September 2, 2009&lt;br /&gt;
If you understand what these two Chicago Tribune developers are up to here (providing savvy online readers with an incrementally improved stylesheet for the recent redesign long before the changes get built into the live site&amp;#8217;s code), then you&amp;#8217;ll understand why I think it&amp;#8217;s pretty cool of them.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.newsless.org/2009/09/five-concrete-steps-to-improving-the-news/"&gt;Five concrete steps to improving the news&lt;/a&gt;&lt;br /&gt;
Newsless.org | September 1, 2009&lt;br /&gt;
Matt Thompson follows up his post about what goes missing from most news stories with a few suggestions for how to roll out a contextual approach to a news story. I like #4, which includes this idea: &amp;#8220;Keep a public list of the most important things you don’t know about your topic.&amp;#8221;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.serramedia.com/blog/2009/09/02/new-report-how-to-build-a-user-community-online/"&gt;New report: How to build a user community online&lt;/a&gt;&lt;br /&gt;
Mark Briggs of Journalism 2.0 and his team at Serra Media put together this great report on community management.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.readwriteweb.com/archives/young_families_are_now_the_early_adopters.php"&gt;Young Families are the Real Early Adopters&lt;/a&gt;&lt;br /&gt;
Mash this market research up with the right Pew report, and you&amp;#8217;ll have a good idea of how to deliver the news to an audience that is the most likely to want it.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://twitter.com/mattwaite/status/3711045616"&gt;mattwaite&lt;/a&gt;: Today, we launched Home Team, a local high school sports site: &lt;a title="Click here to view this link!" href="http://hometeam.tampabay.com/"&gt;http://hometeam.tampabay.com/&lt;/a&gt; And I now I need to sleep for a month.&lt;br /&gt;
Twitter | September 2, 2009&lt;br /&gt;
Matt and company at the St. Petersburg Times demonstrating what a solid Web framework and some experience can help you get done in a short span of time. More details in the tweets that followed this one.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.steverubel.com/lifestreaming-newspaper-uses-posterous-to-sol"&gt;Lifestreaming: Newspaper Uses Posterous to Solicit and Publish Reader Photos&lt;/a&gt;&lt;br /&gt;
The Steve Rubel Lifestream | August 30, 2009&lt;br /&gt;
Did you spot the Austin American-Statesman using Posterous to collect reader photos last week?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So, are you caught up?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If Posterous, Django, market research, community management, contextual news, CSS, the Knight News Challenge, and CoPress are all alien objects to you, &lt;strong&gt;pick any one&lt;/strong&gt; and get up to speed.&lt;/p&gt;
&lt;p&gt;Catch up or get left behind.&lt;br /&gt;
&lt;h3&gt;Previously&lt;/h3&gt;
&lt;ul class="related_post"&gt;
&lt;li&gt;&lt;a href="http://ryansholin.com/2009/07/02/announcing-reportingon-2-0-is-live/" title="Announcing: ReportingOn 2.0 is live"&gt;Announcing: ReportingOn 2.0 is live&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ryansholin.com/2008/10/03/idealab-diy-django-development-at-reportingon/" title="IdeaLab: DIY Django development at ReportingOn"&gt;IdeaLab: DIY Django development at ReportingOn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://ryansholin.com/2008/10/01/launching-reportingon-10/" title="Launching ReportingOn 1.0"&gt;Launching ReportingOn 1.0&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ryansholin?a=e_xSLiaC_Go:pRH2H1-3t74:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ryansholin?i=e_xSLiaC_Go:pRH2H1-3t74:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ryansholin?a=e_xSLiaC_Go:pRH2H1-3t74:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ryansholin?i=e_xSLiaC_Go:pRH2H1-3t74:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ryansholin?a=e_xSLiaC_Go:pRH2H1-3t74:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ryansholin?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ryansholin?a=e_xSLiaC_Go:pRH2H1-3t74:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ryansholin?i=e_xSLiaC_Go:pRH2H1-3t74:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><pubDate>Wed, 02 Sep 2009 21:28:43 GMT</pubDate><guid isPermaLink="false">http://ryansholin.com/?p=1646</guid><comments>http://ryansholin.com/2009/09/02/catch-up-or-get-left-behind/#comments</comments><author>Ryan Sholin</author><source url="http://feeds.feedburner.com/ryansholin">Invisible Inkling</source><ng:postId>10438023656</ng:postId><ng:feedId>693216</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>Participatory Politics Foundation: Rails Programmer</title><link>http://jobs.37signals.com/jobs/5545</link><description>

&lt;p&gt;
  &lt;strong&gt;Location:&lt;/strong&gt; New York, NY
    &lt;br /&gt;&lt;strong&gt;URL:&lt;/strong&gt; &lt;a href="http://www.participatorypolitics.org/"&gt;http://www.participatorypolitics.org/&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;We&amp;#8217;re a non-profit organization that builds open-source web tools for political engagement. We believe the web presents an unprecedented opportunity to amplify political actions and make politics more widely accessible.&lt;/p&gt;
&lt;p&gt;Our flagship project is the government transparency site OpenCongress, a joint project with the Sunlight Foundation ::&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.opencongress.org/"&gt;http://www.opencongress.org/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;#8230; the site&amp;#8217;s code is free, open-source, and non-commercial, written primarily in Ruby on Rails.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re seeking an experienced Rails programmer, one who shares our principles of facilitating broad-based political engagement, to join our development team on OpenCongress. As a new full-time programmer, you&amp;#8217;d be involved in all aspects of site development, including building new features &amp;amp; integrating new data sets. Solid experience with Ruby on Rails is required &amp;#8212; knowledge of postgres database is a bonus, but not necessary.&lt;/p&gt;
&lt;p&gt;Ideally, you&amp;#8217;d be based in the New York City area, but we&amp;#8217;re flexible &amp;#8212; feel free to apply wherever you&amp;#8217;re based. Women and people of color are encouraged to apply. We&amp;#8217;re a free-culture-friendly, collaborative crew, so feel free to get in touch, we&amp;#8217;d like to hear from you.&lt;/p&gt;


&lt;p&gt;&lt;strong&gt;To apply:&lt;/strong&gt; Send a resume and a brief note of intro to &lt;a href="&amp;#109;&amp;#97;&amp;#105;&amp;#108;&amp;#116;&amp;#111;&amp;#58;%64%72%6d@%70%70%6f%6c%69%74%69%63%73.%6f%72%67"&gt;drm@ppolitics.org&lt;/a&gt;&lt;/p&gt;
</description><pubDate>Wed, 02 Sep 2009 02:26:19 GMT</pubDate><guid isPermaLink="false">http://jobs.37signals.com/jobs/5545</guid><source url="http://jobs.37signals.com/jobs.rss">Recent Jobs</source><ng:postId>10433669494</ng:postId><ng:feedId>1316727</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>jQTouch, a jQuery plugin for mobile web development on WebKit devices</title><link>http://www.jqtouch.com/</link><description>&lt;a href="http://www.jqtouch.com/"&gt;jQTouch&lt;/a&gt;, "a jQuery plugin for mobile web development on the iPhone, Android, Palm Pre, and other forward-thinking devices," is now available in public beta. This obviously blurs the line rather extensively between native app and web app and, as such, I'm still formulating an opinion. But the approach to cater to WebKit-enabled devices is a plus one.</description><pubDate>Mon, 31 Aug 2009 16:50:52 GMT</pubDate><guid isPermaLink="false">http://www.jqtouch.com/</guid><source url="http://www.cameronmoll.com/rss/linkage/index.xml">Authentic Boredom ~ Premium Linkage</source><ng:postId>10425672490</ng:postId><ng:feedId>47524</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>No Surprises</title><link>http://www.randsinrepose.com/archives/2009/08/31/no_surprises.html</link><description>&lt;p&gt;At the end of each fiscal year, companies take stock of their performance. &lt;em&gt;How'd we do? Better or worse? &lt;/em&gt;This is a natural time to reflect upon individual performance -- this is when your boss writes your review. &lt;/p&gt;

&lt;p&gt;In my ideal management world, a review is simply a documentation of well-known facts, your performance over the year. It also contains constructive advice and insight regarding how your boss believes you can improve on that performance. My dream is that you already know all of this information because you've been getting year-round feedback from your boss.&lt;/p&gt;

&lt;p&gt;I wish.&lt;/p&gt;

&lt;p&gt;Whether your manager is consistently delivering this information or not, the feedback, written down, is completely different from receiving it verbally. The path to your brain via the written word is dramatically different than for the spoken word. Reading the highs and lows of the past year makes them permanent and makes them real.&lt;/p&gt;

&lt;p&gt;And then there's the surprise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Show Me the Money&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bad news. The surprise has nothing to do with money. We're not talking about compensation here. Yes, you did a splendid job this year and I think they should be throwing raises, bonuses, and stock your way. But it's even better if it's clear why you think you did a splendid job. Can you articulate it? And you might know, but does your boss? Can he explain to you, in detail, how well you kicked ass?&lt;/p&gt;

&lt;p&gt;I didn't think so.&lt;/p&gt;

&lt;p&gt;See, your boss has you and a bunch of other yous who are all allegedly kicking ass, and all of that ass kickery is tricky to monitor, especially over an entire year. It gets even worse when one of your team members is not kicking ass. Legitimately or not, that's actually where a lot of your boss' attention is going. You read that right: someone else's failure is distracting from your phenomenal year.&lt;/p&gt;

&lt;p&gt;Let's fix that.&lt;/p&gt;

&lt;p&gt;There are three strategies I'd like you to employ when it comes to your yearly review. They are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ignore the measures, focus on the content.&lt;/li&gt;
&lt;li&gt;Prepare for the fact a review is a discussion and, sometimes, a negotiation.&lt;/li&gt;
&lt;li&gt;Deconstruct the surprise.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Measures versus Content&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I've experienced a lot of different review formats at different companies, but let's boil it down to three buckets. A review describes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What you did.&lt;/li&gt;
&lt;li&gt;How you did it.&lt;/li&gt;
&lt;li&gt;What you need to do next.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is a massive simplification of your review. Your review has all sorts of other corporate and division focus areas, but these impressive sounding labels are still just lenses through which you understand how you did versus what was expected.&lt;/p&gt;

&lt;p&gt;For each of the buckets, there are two classes of information: the content and the measure. I want to explain how you can save yourself a lot of sleepless nights ignoring the measures, but first, a definition.&lt;/p&gt;

&lt;p&gt;Sprinkled across your review are measures. These are words like "Needs Improvement", "Satisfactory", or "Excellent". These words grab you because they're easy to understand. They are effectively your grades, and you've spent a lot of your formative years waiting for grades to show up. &lt;/p&gt;

&lt;p&gt;If I told you that you got an A on a piece of work, you'd internally translate that letter into a pleasant, "I did about as well as I could. Go me." Grades - measures - are efficient, they do convey information, but they lack essential content. I'll explain via example.&lt;/p&gt;

&lt;p&gt;When I arrived at University of California, Santa Cruz in the 90s, they had no grades. Hippies. At the end of the quarter, you received a written evaluation. For each student in the class, the professor or the teaching assistant would produce a written evaluation -- a plain English description of the type and quality of the work produced over the semester.&lt;/p&gt;

&lt;p&gt;I don't know who came up with the idea of ditching grades, but my hope was that they wanted to ditch the measures. The intent of measures are not to derive useful information, they are designed to allow for comparison and, duh, measurement. Am I higher or lower than you? How many As? Are there more As than Bs? It's interesting data and I'm sure if you took a classroom full of data and plotted it on a graph, you'd learn something. Look! A bell curve! &lt;/p&gt;

&lt;p&gt;A measure doesn't help you in your career. Your performance review isn't about comparisons to others. They're about what you did and what you could do. What you're looking for is the content.&lt;/p&gt;

&lt;p&gt;Tell me which is more useful:&lt;/p&gt;

&lt;p&gt;"You did well."&lt;/p&gt;

&lt;p&gt;-or-&lt;/p&gt;

&lt;p&gt;"You finished the work on schedule, the customer was happy with the results, but there were lingering quality issues with the code. Looking at the last two releases, you had 2x the numbers of bugs than in prior releases. Focus on..."&lt;/p&gt;

&lt;p&gt;We get hung up on grades, on measures, because they are so gosh darned digestible. They give us the illusion that they show us where we fit, but they don't tell us what next?&lt;br /&gt;
 &lt;br /&gt;
At UCSC, the point of the gradeless report card was to create a vacuum where the professor would actually say something useful. You're not going to get rid of measures -- they serve a distinct purpose -- but when you're first reading your review, I want you to ignore those seductive one-word assessments of your entire year. Their simplicity, while comprehensible, is just going to obscure the complexity of your year.&lt;/p&gt;

&lt;p&gt;Rather, look at the content behind the measures. Whatever your particular areas of focus are, does your boss do an effective job of explaining what you did, how you did, and what you could do better? It's a simple set of requirements, but your boss is going to mess it up, which is why you need to be clear that...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A Review is a Conversation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The written word is intimidating. An assessment of a year is a big deal, so what are you going to do when you sit down with your boss and he hands you three poorly crafted paragraphs littered with the word "significant"?&lt;/p&gt;

&lt;p&gt;No, you don't ask about the raise. You freak out about the paragraphs. THREE PARAGRAPHS? I'VE WRITTEN MORE IN EMAIL THIS MORNING THAN YOU JUST WASTED ON MY YEAR. &lt;/p&gt;

&lt;p&gt;Calm yourself. &lt;/p&gt;

&lt;p&gt;Think of this pathetic piece of paper as an opening offer -- a poor offer. Your job is to transform this travesty into an accurate reflection of your year and you're not doing this just out of a sense of self-righteousness, you're doing to get the set the record straight.&lt;/p&gt;

&lt;p&gt;This piece of paper is one of the only official documents of your career at this company. If you move, if your boss leaves, if there's a reorg, this is often the first document reviewed to understand the degree of your asskickery and that means you want your boss to comprehend it.&lt;/p&gt;

&lt;p&gt;"But Rands, I was just... so pissed. Three paragraphs? I spent my entire winter on the project. I was FURIOUS."&lt;/p&gt;

&lt;p&gt;Again, your review will contain surprises, and they will rattle you, which is why you prepare with a self review.&lt;/p&gt;

&lt;p&gt;Whether your company asks for it or not, the moment the mail from HR alerts you to the review season, you start cobbling together your self review. Same buckets as above. My move is to keep a yearlong log of significant work as a task in whatever task tracking system I'm currently ignoring. Even if you haven't been paying consistent attention, you'll be surprised by what you can dig up in a weekend of considering your year.&lt;/p&gt;

&lt;p&gt;Take a look at your year. How'd you do? No, really, I'm not actually reading it so you can have an honest opinion. Was it a great year or did you just think it was great? Yes, your boss' opinion about your year is key, he does sign the checks, but it's a key surprise reducing technique to walk into the review with an opinion. This moment of personal honesty you're having with yourself is a big deal because that's the foundation you're going to stand on when the three pathetic paragraphs show up. Having a justifiable opinion regarding your year is a powerful, defensible position.&lt;/p&gt;

&lt;p&gt;While it's important to send the self review long before your boss writes his review, it's more important that you have this opinion, this well-defined opinion, when sitting down to read your boss' review. Does it document what you did? Everything? Does the description of what you did match your perception? No? Why? Don't tell me, tell your boss, and make sure he gets it because it's these types of historical perception mismatches that form an unhealthy basis for emerging misunderstanding and resentment. &lt;/p&gt;

&lt;p&gt;The point of a review is he debate -- to align your perceptions with those of the person who signs the checks, but even with all this structured healthy debate, there's still going to be a... &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Surprise!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I don't know what the surprise is. It's your review. Some of the doozies over the years from mine include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The total absence of recognition for a multi-month multi-team project that kicked ass.&lt;/li&gt;
&lt;li&gt;A reversal of opinion regarding a piece of work I'd done, usually towards the negative.&lt;/li&gt;
&lt;li&gt;Completely contradictory areas of improvement.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unfortunately, the surprise is the point. A review not only forces the alignment discussion, it serves as a warning for the coming year: &lt;em&gt;What do I need to do differently to avoid being blindsided when the next review arrives?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Fact is, you're never fully going to get your boss on-board with your year. There are opinions he has which aren't going to change which means if you don't want another surprise next year, you have to change. &lt;/p&gt;

&lt;p&gt;A review's value lies not only in the documentation of what was observed, but also what was not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Permanence of the Written&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In many years of reviews, the only consistency I've noticed is that they're getting shorter. My unsubstantiated paranoia is that lawyers apply subtle corporate pressure to retain less descriptive documentation of what actually happened in the company. But perhaps it's just a growing professional laziness. &lt;/p&gt;

&lt;p&gt;Whatever the reason, a brief review is just sad. If you're staring at three useless paragraphs, you have a couple of problems. You've got a company that allows crappy reviews and you've got a boss who is unable or unwilling to articulate either the quantity or quality of work you've done.&lt;/p&gt;

&lt;p&gt;That's all sorts of screwed, but it's only complete breakdown only occurs when you don't react.&lt;/p&gt;

&lt;p&gt;The first review I wrote was awful. It was three paragraphs derived from scanning status reports from the past six months. I sat in the room as she read the review and she didn't have to say a thing for me to understand that I'd be spending the weekend actually writing the review. I got an accusing, furious glare. &lt;em&gt;You didn't even try.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So I did.&lt;/p&gt;</description><pubDate>Mon, 31 Aug 2009 04:23:58 GMT</pubDate><guid isPermaLink="false">499@http://www.randsinrepose.com/</guid><author>michael.lopp@gmail.com</author><source url="http://www.randsinrepose.com/index.xml">Rands In Repose</source><ng:postId>10422975805</ng:postId><ng:feedId>5180</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>Little, shiny robots</title><link>http://pivotallabs.com/users/amilligan/blog/articles/950-little-shiny-robots</link><description>&lt;p&gt;One of my favorite computer games when I was growing up was &lt;a href="http://en.wikipedia.org/wiki/Robot_Odyssey"&gt;Robot Odyssey&lt;/a&gt;; I imagine it will come as a surprise to no one that I was a nerdy kid.  This article is a little bit of a tribute to that game, and the coolness of solving complex problems with a handful of simple concepts combined in clever ways.&lt;/p&gt;

&lt;p&gt;Imagine you want to write a web-based game that involves robots.  The robots in your game are a bit like the robots in Robot Odyssey: you program them with a list of simple instructions and when you turn them on they follow those instructions faithfully.  Let's say, for the sake of argument, that your robots can Walk Forward, Turn Left, Turn Right, Jump, and Beep.&lt;/p&gt;&lt;p&gt;You model each of the moves your Robot can make as an Action, and a Program as a list of Actions.  Since each Robot can execute any number of Actions as part of its Program, and any number of Robots can execute Actions, you join Programs and Actions through the Instructions table.  Like so:&lt;/p&gt;

&lt;pre&gt;
class Robot &amp;lt; ActiveRecord::Base
  has_one :program
end

class Program &amp;lt; ActiveRecord::Base
  belongs_to :robot
  has_many :instructions
  has_many :actions, :through =&amp;gt; :instructions
end
&lt;/pre&gt;

&lt;p&gt;You build a whiz-bang interface for programming each Robot using JavaScript, which will PUT a collection of Action IDs to programs#update &amp;#40;each Robot creates a blank program on initialization, so no need for programs#create&amp;#41;.  &lt;/p&gt;

&lt;p&gt;This seems pretty straightforward, doesn't it?  Unfortunately, it won't work; the update will fail to reliably record the uploaded Actions.  Here are some examples:&lt;/p&gt;

&lt;pre&gt;
@program.action_ids  # []
@program.action_ids = [1, 4] # Forward, Jump

@program.action_ids # [1, 4]
@program.action_ids = [3, 1, 2, 5] # Right, Forward, Left, Beep

@program.action_ids # [3, 1, 2, 5]
@program.action_ids = [5, 5, 5] # Beep, Beep, Beep

@program.action_ids # [5]   ?????
&lt;/pre&gt;

&lt;p&gt;What happened here?  The problem lies with the way ActiveRecord collection associations update themselves.  Here is the interesting code &amp;#40;slightly paraphrased&amp;#41; from association_collection.rb:&lt;/p&gt;

&lt;pre&gt;
# Replace this collection with +other_array+
# This will perform a diff and delete/add only records that have changed.
def replace&amp;#40;other_array&amp;#41;
  ...
  delete&amp;#40;@target.select { |v| !other_array.include?&amp;#40;v&amp;#41; }&amp;#41;
  concat&amp;#40;other_array.select { |v| !@target.include?&amp;#40;v&amp;#41; }&amp;#41;
end
&lt;/pre&gt;

&lt;p&gt;As you can see &amp;#40;or you could just read the comment&amp;#41;, this only adds an element to a collection if that element isn't already in the collection &amp;#40;and it acts similarly for deletion&amp;#41;.  Sadly, it doesn't take into account how many times an element appears.  So, above, when I tried set the action_ids to [5, 5, 5] it saw that the action_ids collection already contained that ID and moved on.  If I had set the action_ids collection to [5, 5, 5] when it already contained [1, 4], the result would have been the expected [5, 5, 5].&lt;/p&gt;

&lt;p&gt;Now, I'm on the fence with regard to whether I consider this a bug or just a somewhat inconsistent, but expected, behavior.  To begin with, the fix is annoyingly nontrivial, and would potentially have a noticeable performance impact.  Far more importantly, I'm not sure how often this might reasonably cause a real problem.  In the case of your Robots game, you'd probably care quite a lot about what order your Robot executes its Actions in, so you'd likely have a position column, or something similar, on the instructions table.  Given that, you'd probably update the Program by sending in a list of nested attributes which would create Instructions, each with the correct position and associated to the correct Action.&lt;/p&gt;

&lt;p&gt;Even so, this is behavior worth knowing about.  In the infinitude of possible update scenarios someone will want to update their HMT associations this way.  I know I initially wrote code to do this as a temporary experiment, and ended up spending the rest of the day trying to figure out why my updates did the wrong thing a small percentage of the time.&lt;/p&gt;</description><pubDate>Sun, 30 Aug 2009 03:01:00 GMT</pubDate><guid isPermaLink="false">http://pivotallabs.com/users/amilligan/blog/articles/950-little-shiny-robots</guid><author>Adam Milligan</author><source url="http://feeds.feedburner.com/pivotallabs/blabs.atom">Pivotal Blabs</source><ng:postId>10419205923</ng:postId><ng:feedId>1320530</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>All About Placebo</title><link>http://feedproxy.google.com/~r/LoneGunman/~3/mN6JQwmfm_A/</link><description>&lt;p&gt;&lt;em&gt;Wired&lt;/em&gt; has published what must be &lt;a title="Placebos Are Getting More Effective. Drugmakers Are Desperate to Know Why. - Wired" href="http://www.wired.com/medtech/drugs/magazine/17-09/ff_placebo_effect?currentPage=all"&gt;&lt;em&gt;&lt;strong&gt;one of the most comprehensive articles looking at the phenomenon of the placebo effect&lt;/strong&gt;&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From its humble beginnings in WWII with anesthetist &lt;a title="Henry K. Beecher - Wikipedia" href="http://en.wikipedia.org/wiki/Henry_K._Beecher"&gt;Henry Beecher&lt;/a&gt; to the placebo&amp;#8217;s transition from being treated as a purely psychological trait to a physiological one; there&amp;#8217;s some great material here.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Two comprehensive analyses of antidepressant trials have uncovered a dramatic increase in placebo response since the 1980s. One estimated that the so-called &lt;a title="Effect Size - Wikipedia" href="http://en.wikipedia.org/wiki/Effect_size"&gt;effect size&lt;/a&gt; (a measure of statistical significance) in placebo groups had nearly doubled over that time.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s not that the old meds are getting weaker, drug developers say. It&amp;#8217;s as if the placebo effect is somehow getting stronger.&lt;/p&gt;
&lt;p&gt;The fact that an increasing number of medications are unable to beat sugar pills has thrown the [pharmaceutical] industry into crisis. The stakes could hardly be higher. In today&amp;#8217;s economy, the fate of a long-established company can hang on the outcome of a handful of tests.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Related: &lt;a title="Placebo in History - Wikipedia" href="http://en.wikipedia.org/wiki/Placebo_in_history"&gt;Placebo in History&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;via &lt;a title="Jonah Lehrer on Twitter" href="http://twitter.com/jonahlehrer/status/3520928456"&gt;@jonahlehrer&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;&lt;strong&gt;You may also be interested in:&lt;/strong&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.lonegunman.co.uk/2008/05/28/the-placebo-effect-once-more-with-feeling/" rel="bookmark" title="28 May, 2008"&gt;The Placebo Effect &amp;#8211; Once More With Feeling&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="http://www.lonegunman.co.uk/2008/08/28/exercise-and-the-placebo-effect/" rel="bookmark" title="28 August, 2008"&gt;Exercise and the Placebo Effect&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="http://www.lonegunman.co.uk/2009/04/07/ideology-getting-in-the-way-of-evidence-based-medicine/" rel="bookmark" title="7 April, 2009"&gt;Ideology Getting in the Way of Evidence-Based Medicine&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;!-- Similar Posts took 48.861 ms --&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/LoneGunman?a=mN6JQwmfm_A:WB0055gnG98:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LoneGunman?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LoneGunman?a=mN6JQwmfm_A:WB0055gnG98:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LoneGunman?i=mN6JQwmfm_A:WB0055gnG98:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/LoneGunman?a=mN6JQwmfm_A:WB0055gnG98:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/LoneGunman?i=mN6JQwmfm_A:WB0055gnG98:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/LoneGunman/~4/mN6JQwmfm_A" height="1" width="1"/&gt;</description><pubDate>Wed, 26 Aug 2009 08:16:31 GMT</pubDate><guid isPermaLink="false">http://www.lonegunman.co.uk/?p=3610</guid><comments>http://www.lonegunman.co.uk/2009/08/26/all-about-placebo/#comments</comments><author>Lloyd Morgan</author><source url="http://www.lonegunman.co.uk/feed/">Lone Gunman</source><ng:postId>10399097976</ng:postId><ng:feedId>4003088</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>Ruby On Rails Developer (Ongoing) (Ann Arbor, MI (Telecommuting Possible))</title><link>http://feedproxy.google.com/~r/FSAllJobs/~3/gaNPFH3fvzA/4367</link><description>&lt;p&gt;We&amp;#8217;re looking for an Ruby / Ruby on Rails developer with an eye for
detail and a drive to learn and improve his or her skill set while
working in a fast-paced environment. At MetaSpring, you&amp;#8217;ll be
developing a diverse range of dynamic, Web 2.0 applications and working
with our designers to tie in slick and usable front end interfaces. The
ability to handle server administration tasks as they arise is a big
plus.&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;&lt;br&gt;&lt;b&gt;&lt;br&gt;Required Skills &amp;amp;amp; Knowledge&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;&lt;/b&gt;&lt;ul&gt;&lt;li&gt;A solid understanding of the web from philosophical foundations to the nuts and bolts of its implementation&lt;/li&gt;&lt;li&gt;The ability to create good abstractions that actually get reused&lt;/li&gt;&lt;li&gt;Experience developing front end components utilizing XHTML, CSS, JavaScript, AJAX, XML, JSON and microformats&lt;/li&gt;&lt;li&gt;Experience delivering non-trivial production-ready Ruby on Rails code&lt;/li&gt;&lt;li&gt;Experience with MySQL and database architecture&lt;/li&gt;&lt;li&gt;Exceptional problem solving skills&lt;/li&gt;&lt;li&gt;Experience with cross-browser development and all of the fun challenges that this entails&lt;/li&gt;&lt;li&gt;A familiarity with Agile Development practices&lt;/li&gt;&lt;/ul&gt;&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;&lt;b&gt;What would be extra awesome:&lt;/code&gt;&lt;/pre&gt;


	&lt;pre&gt;&lt;code&gt;&lt;/b&gt;&lt;ul&gt;&lt;li&gt;Solid communication skills&lt;/li&gt;&lt;li&gt;Knowledge of Photoshop, Flash, etc&lt;/li&gt;&lt;li&gt;A flair for the written word&lt;/li&gt;&lt;li&gt;Any server administration experience&lt;/li&gt;&lt;li&gt;A passion for usability&lt;/li&gt;&lt;li&gt;Familiarity with the Mac development environment&lt;/li&gt;&lt;/ul&gt;&lt;/code&gt;&lt;/pre&gt;</description><pubDate>Fri, 21 Aug 2009 21:05:20 GMT</pubDate><guid isPermaLink="false">http://jobs.freelanceswitch.com/jobs/4367</guid><source url="http://feeds.feedburner.com/FSAllJobs">FreelanceSwitch Job Board: All Jobs</source><ng:postId>10380786398</ng:postId><ng:feedId>1828584</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title /><link>http://www.chicagobusiness.com/cgi-bin/article.pl?page_id=2342&amp;plckController=Blog&amp;plckScript=blogScript&amp;plckElementId=blogDest&amp;plckBlogPage=BlogViewPost&amp;plckPostId=Blog%3a16ea2629-7e90-46f0-a706-dd6152764513Post%3ac6e6d5be-3544-47d5-9ed4-bf72e9d026e6&amp;sid=sitelife.chicagobusiness.com&amp;seenIt=1&amp;seenIt=1</link><description /><pubDate>Thu, 20 Aug 2009 04:39:08 GMT</pubDate><guid isPermaLink="false">tag:newsgator.com,2006:Feed.aspx/-1/10365182036</guid><source url="http://services.newsgator.com/urlclippedposts.aspx">URL clipped post</source><ng:postId>10365182036</ng:postId><ng:feedId>-1</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>The case for innovation</title><link>http://wemediaguru.com/2009/08/19/the-case-for-innovation/</link><description>&lt;div class='snap_preview'&gt;&lt;br /&gt;&lt;p&gt;Sometimes things are all about timing. The last two days I’ve come across four things that I needed to read and the very moment they came around.&lt;/p&gt;
&lt;p&gt;They all have to do with innovation, taking risks and breaking down barriers. Engaging in those and taking a critical look at the tasks I’ve been doing, has given me some of the fire back that has been absent for awhile, so I felt a need to share. Here goes:&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;first &lt;/strong&gt;is a video from the folks at &lt;a href="http://www.copress.org/"&gt;CoPress&lt;/a&gt; called A Case for Innovation. Simple, to the point and right on.&lt;/p&gt;
&lt;p&gt;&lt;span style='text-align:center; display: block;'&gt;
&lt;object type="application/x-shockwave-flash" width="400" height="300" data="http://www.vimeo.com/moogaloop.swf?clip_id=6172232&amp;amp;server=www.vimeo.com&amp;amp;fullscreen=1&amp;amp;show_title=1&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=01AAEA"&gt;
	&lt;param name="quality" value="best" /&gt;
	&lt;param name="allowfullscreen" value="true" /&gt;
	&lt;param name="scale" value="showAll" /&gt;
	&lt;param name="movie" value="http://www.vimeo.com/moogaloop.swf?clip_id=6172232&amp;amp;server=www.vimeo.com&amp;amp;fullscreen=1&amp;amp;show_title=1&amp;amp;show_byline=0&amp;amp;show_portrait=0&amp;amp;color=01AAEA" /&gt;
&lt;/object&gt;
&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;second &lt;/strong&gt;is a post by Dan Pacheco on &lt;a href="http://www.pbs.org/idealab/2009/08/how-fear-brand-addiction-and-paranoia-block-innovation212.html"&gt;how fear, brand addiction and paranoia block innovation&lt;/a&gt;. This struck with me because breaking down these and other barriers is going to lead to some really cool stuff.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Just to be clear, I&amp;#8217;m not opposed to building and growing existing brands, but in today&amp;#8217;s fragmented world I think that &amp;#8220;one size fits all&amp;#8221; brands have limited appeal. My advice to mature information companies is to think of their brands as &amp;#8220;wrappers&amp;#8221; for capabilities and expertise. They deliver solutions to customers. But every audience prefers different packaging, so if you use the same brand for everything you end up polluting their potential.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The &lt;strong&gt;third &lt;/strong&gt;is&lt;strong&gt; &lt;/strong&gt;a very clear set of tasks that can be done to create a ecosystem of local knowledge. It comes from Chuck Peters in a post called &lt;a href="http://chuckpeters.iowa.com/2009/08/focus-on-essential-new-tasks/"&gt;Focus on Essential New Tasks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It is a collaborative blueprint for fundamentally changing the way media companies collect content, engage audiences and new voices, disseminate information and work more closely with communities they serve.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;We need to create content in the first instance with a new mindset, both those content creators we employ full time, and contracted or freelance community content creators.  All content creators need to have a primary emotional bond with their content and audience, not a product or company.&lt;/p&gt;
&lt;p&gt;This content creation needs to take place in a new &lt;a href="http://chuckpeters.iowa.com/2008/12/information-in-the-first-instance/"&gt;infrastructure&lt;/a&gt; which allows atomization and tagging at the simplest elemental level.  Today we are stuck with locked-down story and advertising publishing systems, and a bewildering array of blogs, tweets and social space entries.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The fourth comes from Neil Perkin and his &lt;a href="http://neilperkin.typepad.com/"&gt;Only Dead Fish&lt;/a&gt; blog. If you&amp;#8217;ve never come across him, take the time. It&amp;#8217;s worth it.&lt;/p&gt;
&lt;p&gt;He recently wrote a post about the &lt;a href="http://neilperkin.typepad.com/only_dead_fish/2009/07/the-story-engine.html"&gt;power of incomplete ideas&lt;/a&gt;, which to me speaks directly to the way innovation often happens.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;As Matthew May says in the introduction to his &lt;a href="http://www.changethis.com/58.01.CreativeElegance"&gt;lovely manifesto on the subject&lt;/a&gt; (HT to &lt;a href="http://www.johnniemoore.com/blog/archives/002210.php"&gt;Johnnie Moore&lt;/a&gt; for the link): &amp;#8220;Conventional wisdom says that to be successful, an idea must be concrete, complete, and certain. But what if that’s wrong? What if the most elegant, most imaginative, most engaging ideas are none of those things?&amp;#8221;. Matthew goes on to make a brilliant point about this, that it is the &amp;#8220;unusually simple yet thoughtful construction of what is there&amp;#8221; that gives the missing piece its surprising power. Rather like Itay Talgam&amp;#8217;s &lt;a href="http://neilperkin.typepad.com/only_dead_fish/2009/06/doing-by-not-doing.html"&gt;&amp;#8216;Doing By Not Doing&amp;#8217;&lt;/a&gt; (if you haven&amp;#8217;t seen that talk yet, watch it. It&amp;#8217;s worth it).&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;I am a media junkie and love the idea of forging ahead and breaking down barriers to lead to new success stories in this industry. I take these four items as a call to action.&lt;/p&gt;
  &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/wemediaguru.wordpress.com/310/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/wemediaguru.wordpress.com/310/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/wemediaguru.wordpress.com/310/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/wemediaguru.wordpress.com/310/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/wemediaguru.wordpress.com/310/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/wemediaguru.wordpress.com/310/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/wemediaguru.wordpress.com/310/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/wemediaguru.wordpress.com/310/" /&gt;&lt;/a&gt; &lt;a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/wemediaguru.wordpress.com/310/"&gt;&lt;img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/wemediaguru.wordpress.com/310/" /&gt;&lt;/a&gt; &lt;img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=wemediaguru.com&amp;blog=2563453&amp;post=310&amp;subd=wemediaguru&amp;ref=&amp;feed=1" /&gt;&lt;/div&gt;</description><pubDate>Wed, 19 Aug 2009 18:55:14 GMT</pubDate><guid isPermaLink="false">http://wemediaguru.com/?p=310</guid><comments>http://wemediaguru.com/2009/08/19/the-case-for-innovation/#comments</comments><author>wemediaguru</author><source url="http://wemediaguru.com/feed/">Jason Kristufek's We Media blog</source><ng:postId>10362933617</ng:postId><ng:feedId>2403024</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>10 Vital Lessons for Web Start-Ups</title><link>http://carsonified.com/blog/business/10-vital-lessons-for-web-start-ups/</link><description>&lt;div class="tweetmeme_button" style=""&gt;&lt;a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fbusiness%2F10-vital-lessons-for-web-start-ups%2F"&gt;&lt;img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fcarsonified.com%2Fblog%2Fbusiness%2F10-vital-lessons-for-web-start-ups%2F" height="61" width="51" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;a href="http://events.carsonified.com/fowa/2009/london/schedule?utm_source=TV&amp;amp;utm_medium=banner&amp;amp;utm_campaign=Kevin%2Band%20Gary%20Show"&gt;&lt;img src="http://ryancarson.com/uploads/kevin_gary.png" alt="Kevin and Gary show at FOWA London" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This summer we launched &lt;a href="http://grabaperch.com"&gt;Perch&lt;/a&gt; as a side project from our web development agency, &lt;a href="http://edgeofmyseat.com"&gt;edgeofmyseat.com&lt;/a&gt;. Perch is a really little content management system aimed at web designers who want to enable their clients to update their own site content. As this is our first product (we normally work on website projects for design agencies), there were quite a lot of new things for us to learn.&lt;/p&gt;
&lt;p&gt;In this post I’ll cover some of the things we’ve learned along the way. Whilst the same lessons won’t apply completely to every situation, they’ll be interesting to anyone thinking about launching a web app.&lt;/p&gt;
&lt;p&gt;&lt;span id="more-2930"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;#1 Choose Your Payment Provider Carefully&lt;/h3&gt;
&lt;p&gt;Rather than operating as a hosted service, Perch is a &lt;span class="caps"&gt;PHP&lt;/span&gt; app that you download and install as part of your own website. As such, we’d be selling it from our site via electronic delivery. We decided pretty early on that we were going to sell Perch using PayPal. As our target customers are web designers, we figured that most designers would be familiar with PayPal and probably already have an account. What’s more, it would be easy to integrate into our checkout, still allows customers to pay with a credit card, and there are no up-front fees involved.&lt;/p&gt;
&lt;p&gt;That last point was important, as one of our business decisions with Perch was that we wanted the project to fund itself. Although being born out of a profitable existing business, we wanted to bootstrap Perch as much as possible, so paying a fee for each transaction but nothing up-front suited us just fine. The downside of this is that the fee per transaction is higher than it would be with traditional credit card processing, so there comes a point whereby you’re doing enough credit card business through PayPal that it’s more profitable to pay for the merchant account and payment gateway.&lt;/p&gt;
&lt;p&gt;For Perch, about one third of our payments are with a credit card via PayPal, so we certainly need keep an eye on the figures to make sure we’re getting the most cost effective deal on the processing fees.&lt;/p&gt;
&lt;h3&gt;#2 Know How You’re Going to Deal with Invoicing&lt;/h3&gt;
&lt;p&gt;As a web development agency, we work alongside design agencies building content managed websites and online stores, and typically only deal with a handful of larger invoices each month. However, with Perch we quickly found that we would be facing hundreds of invoices that would all need to be created in our accounts system by hand.&lt;/p&gt;
&lt;p&gt;We use the online accounting software &lt;a href="http://xero.com/"&gt;Xero&lt;/a&gt; for all our accounts, and found that this had a couple of features that would save the day and enable us to handle the volume of invoices more easily. Firstly, we discovered that Xero can import transactions from PayPal just like any other bank account. Once an hour the software updates showing all the new payments that have come in, ready to be matched up with invoices.&lt;/p&gt;
&lt;p&gt;Those invoices are the second half of the problem. Fortunately, Xero has a RESTful &lt;span class="caps"&gt;API&lt;/span&gt; that would enable us to programatically create each customer and invoice in our accounts directly from our web server. This is great, because it means that within about a minute of each sale we’ve got the customer and their invoice set up in Xero, and then within the hour the PayPal transaction appears, ready to be matched up. The only manual part is the matching up, which is very quick to do.&lt;/p&gt;
&lt;p&gt;Using an &lt;span class="caps"&gt;API&lt;/span&gt; to manipulate your business accounts can sound a bit daunting at first, but Xero have a good testing platform to develop against, and our integration was manually checked over before we could go live to make sure that we weren’t doing anything stupid.&lt;/p&gt;
&lt;h3&gt;#3 Be Super-Organised with Customer Support&lt;/h3&gt;
&lt;p&gt;Another new area for us was dealing with end-user support. We were fairly sure we wanted to do this out in public on some sort of forum rather than in email. We felt it was important that customers could search past discussions before posting in case their question had already been answered.&lt;/p&gt;
&lt;p&gt;After looking around at a few different solutions, we discovered &lt;a href="http://tenderapp.com"&gt;Tender&lt;/a&gt;, which seemed to do what we wanted. Crucially, they had an option to point a subdomain at their server so that we could use support.grabaperch.com for our site. This also meant that we could share cookies between our customer account system and the support system on Tender, meaning that, with a quick bit of integration, customers can access both systems with one account.&lt;/p&gt;
&lt;p&gt;One thing we didn’t quite appreciate up front was the distinction between discussion and support. Anything posted to Tender is flagged and requires a response from our team, which is great when customers have issues they need our help resolving. This means that nothing gets missed and on average all support requests are dealt with in under one hour.&lt;/p&gt;
&lt;p&gt;This isn’t so great for general discussion between users, as the environment appears to discourage discussion, as every post is implicitly requesting a formal response. As a reaction to this we’ve just set up a separate community discussion forum where customers can chat and share ideas. We’ll see how that goes – our one concern is that customers will be unsure where they should be posting for help.&lt;/p&gt;
&lt;h3&gt;#4 Provide a Demo&lt;/h3&gt;
&lt;p&gt;One thing we’d seen with other &lt;span class="caps"&gt;CMS&lt;/span&gt; products is the pitifully sad online demo where the login details are published and anyone can go in and have a play. We always felt that the customer experience was pretty bad with these, as each customer ends up looking at a &lt;span class="caps"&gt;CMS&lt;/span&gt; full for everyone else’s test junk. Also, with Perch being designed for small sites, the likelihood of two customers being logged in and attempting to edit the same page at once was fairly high. As soon as that happens the appearance would be that the &lt;span class="caps"&gt;CMS&lt;/span&gt; is behaving erratically. Not good!&lt;/p&gt;
&lt;p&gt;Because of this, we decided we didn’t want an online demo and launched the product without one. Customer feedback quickly told us that that wasn’t going to be good enough, so we had to go back to the drawing board. We were still convinced that a shared online demo would suck, so we decided to provide each customer with their own unique install of Perch to play with.&lt;/p&gt;
&lt;p&gt;We built &lt;a href="http://signup.perchdemo.com"&gt;a system&lt;/a&gt; that enables customers to sign up for a demo. This then automatically installs a new copy of Perch for them and emails the customer their access details. This way, each customer can try the system out without all the usual disadvantages of a shared system.&lt;/p&gt;
&lt;h3&gt;#5 Make it Easy for Customers to Send Feedback&lt;/h3&gt;
&lt;p&gt;At the end of the demo process (each demo site runs for 24 hours) we send the customer an email to thank them for trying out Perch. We thought that this was a great opportunity to find out what they thought of the software. We added the following to the email and hoped for the best.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Loved it? Hated it? One crucial thing missing? Hit reply and let us know – we’ll use your feedback to make Perch better.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Turns out that this was one of the smartest things we did. Asking a customer to just hit reply and talk to us made it so easy for people to respond that more than 25% of customers did just that. We could quickly answer any questions, and most importantly, that we are able to catch those who decided not to buy because they thought Perch was missing a feature that they’d just not spotted. For those who ultimately did walk away, we were able to get an idea of why they chose not to use Perch and we can use that to inform future product decisions.&lt;/p&gt;
&lt;h3&gt;#6 Just because a Market’s busy, Doesn’t Mean it’s Saturated&lt;/h3&gt;
&lt;p&gt;At some points, we’ve stopped to think twice about launching yet another content management system product into the market. There are so many different systems out there, commercial and open source, small and large. The reason that there are so many options is that content management is an extremely broad area, with lots of different customer requirements. What’s more, almost everyone with a website is a potential customer for some sort of &lt;span class="caps"&gt;CMS&lt;/span&gt; of some description, and there’s certainly no shortage of people with websites.&lt;/p&gt;
&lt;p&gt;It’s very tempting to be put off from lunching something just because there are already other products that do a similar job. It’s important to remember that it’s not only the job you do, but how you do it that counts. If your product can offer something different, be that in user experience, a way of working, unusual features, or specialisation for a role or industry, then they’ll be some kind of market for it. There are millions of customers out there. All you need to do is figure out if the potential market is big enough to support your plans.&lt;/p&gt;
&lt;h3&gt;#7 Don’t Worry About the Dinosaurs&lt;/h3&gt;
&lt;p&gt;Right from the start we were sure that Perch had to be built in &lt;span class="caps"&gt;PHP&lt;/span&gt;, as customers would need to be able to get the &lt;span class="caps"&gt;CMS&lt;/span&gt; running easily on their own hosting. &lt;span class="caps"&gt;PHP&lt;/span&gt; is rock solid and super-easy to host. One concern we had was that although &lt;span class="caps"&gt;PHP5&lt;/span&gt; has been around for ages, there are still a lot of servers out there running &lt;span class="caps"&gt;PHP4&lt;/span&gt; even though it’s no longer supported. Projects like WordPress have a goal of being able to run anywhere, and as such stick to the parts of the language only available in &lt;span class="caps"&gt;PHP4&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;As a company, we develop primarily in object-oriented &lt;span class="caps"&gt;PHP5&lt;/span&gt;, and knowing all the advantages that well structured OO code brings, I was reluctant to develop a new app in crufty old &lt;span class="caps"&gt;PHP4&lt;/span&gt; code. We played with the idea of having two versions, but that meant twice the work on new features and twice the bugs to fix. So we just took the plunge and made the app &lt;span class="caps"&gt;PHP5&lt;/span&gt; only, thinking that we’d wait and see if there was any demand for a &lt;span class="caps"&gt;PHP4&lt;/span&gt; version.&lt;/p&gt;
&lt;p&gt;As it turns out, it’s been a complete non-issue. On the occasion when a customer has found their hosting is &lt;span class="caps"&gt;PHP4&lt;/span&gt;, they’ve been able to contact their hosting company and get the site switched to &lt;span class="caps"&gt;PHP5&lt;/span&gt;. It’s all surprisingly low-hassle. Turns out we were worrying about a problem that didn’t even exist.&lt;/p&gt;
&lt;h3&gt;#8 Release Early and Often, but Plan Ahead&lt;/h3&gt;
&lt;p&gt;We often hear the phrase “release early, release often”, but what does that really mean? For us, it meant getting our initial release of Perch to a point where it had just enough functionality to be useful and stopping there and shipping. From a development point of view, releases force you to get bugs tied down, loose ends tied up and get everything properly tested. So a shipping release is a known stable point in where everything is 100% solid and functional. Incrementally adding new features on top of a release then becomes a more reliable process and it’s much easier to keep your application stable.&lt;/p&gt;
&lt;p&gt;When we were building the initial version of Perch I had a whole list of ideas of what features we’d build into 1.1, 1.2 and so on. It’s great that we released early, as it turns out that none of the features I thought were essential have been asked for by customers. I thought we’d need &lt;span class="caps"&gt;RSS&lt;/span&gt; – no one cares about &lt;span class="caps"&gt;RSS&lt;/span&gt; for a small site.&lt;/p&gt;
&lt;p&gt;So whilst you don’t want to spend loads of time building in features before you ship, it is still important to plan ahead and leave doors open for the features you may wish to add further down the line. With Perch, I figured it might be good to have the option of translating the admin interface into different languages. I didn’t have a specific plan for how it would work, and certainly didn’t spend time building it, but what I did do was make sure that every piece of text in the interface was passed through a translation function.&lt;/p&gt;
&lt;p&gt;At the time we launched, my &lt;code&gt;PerchLang::get()&lt;/code&gt; function calls just returned whatever string was passed to them – the function basically did nothing. But it did mean that when I came to implementing translations in version 1.1.5, all I had to do was think of the best way to take a string in English and find the translated version. At the time of writing, Perch is available in 12 customer-contributed languages from Russian to Portuguese, with minimal programming needed.&lt;/p&gt;
&lt;h3&gt;#9 Make Full use of Existing Tools&lt;/h3&gt;
&lt;p&gt;What no one tells you when you launch a product is that about 50% of your effort goes into developing the product, and the other 50% is putting infrastructure in place to market, sell and support it. There’s a lot of work that goes into all the peripheral systems needed, and I think we’d have given up if we tried to implement all that ourselves.&lt;/p&gt;
&lt;p&gt;Instead we made use of PayPal to take funds, Tender to handle the support, we asked people to follow us on Twitter to keep in touch rather than setting up some kind of mailing system. We’ve set up our discussion forums using bbPress. Anywhere where we can make use of an existing solution instead of writing our own, we’ve tried to do so. Not only does it work out more cost effective, it enables us to focus on our main task – building a useful product.&lt;/p&gt;
&lt;h3&gt;#10 Hire in the Experts&lt;/h3&gt;
&lt;p&gt;First and foremost, we’re web developers. That means there are parts of a project that we’ll be good at, but there are going to be parts that are outside our expertise. One thing we’ve learned is that it’s really important to call in the experts to help cover your weak spots.&lt;/p&gt;
&lt;p&gt;The first experts we called in were our solicitors to draft up a professional software license agreement. We could have probably come up with something ourselves, but the chances are that when it came to the crunch it wouldn’t stand up in a court of law and therefore would be worthless. We hope that we never have to test our license in court, but there’s no point in having a cobbled together legal document of any kind – it’s as good as having none.&lt;/p&gt;
&lt;p&gt;The next job that called for experts was with the interface design. We like to think we know one end of a usable interface from the other, but when it comes to the crunch it’s not our core skill. We wanted the UI for Perch to be really well considered, easy to use and something that designers would be happy to hand over to their clients to use. So we called on the help of our friends at &lt;a href="http://ninefour.co.uk"&gt;Nine Four&lt;/a&gt; who were able to take our jumbled prototype UI and turn it into something that really worked.&lt;/p&gt;
&lt;p&gt;When we launched our marketing site, still trying to not spend money we didn’t need to spend, we bought some stock illustration from &lt;a href="http://istockphoto.com"&gt;iStockPhoto&lt;/a&gt; and just ran with it. This was nice and cheap, but long term is was fairly charmless and we didn’t think it wise to build up a brand around illustration that wasn’t technically ours. So shortly after launching, we hired illustrator &lt;a href="http://kevadamson.com"&gt;Kev Adamson&lt;/a&gt; to develop some original illustrations that we could use going forward. The great thing is that now not only is the illustration a thousand times better than what we had from stock, we have someone to go back to for any further work we need doing.&lt;/p&gt;
&lt;p&gt;As an agency we’d be horrified if our customers thought they’d do their web development themselves instead of calling us in to do it properly. We’ve tried to apply the same principal to our own project and call in experts where they can help.&lt;/p&gt;
&lt;h3&gt;In Conclusion&lt;/h3&gt;
&lt;p&gt;Of course these are not universal rules, but they are fairly broad lessons that we’ve learned on our journey so far. Some we knew in theory and have put into practice, and others we’ve picked up along the way. I’m sure as we carry on down the road there’ll be plenty more to learn. Perhaps you’ve had similar – or contrary – experiences, if so leave a comment and tell us about it. And if you ever build small sites for clients, family or organisations you care about, perhaps you’ll &lt;a href="http://grabaperch.com/"&gt;come and check us out&lt;/a&gt;.&lt;/p&gt;
</description><pubDate>Wed, 19 Aug 2009 16:26:24 GMT</pubDate><guid isPermaLink="false">http://carsonified.com/?p=2930</guid><comments>http://carsonified.com/blog/business/10-vital-lessons-for-web-start-ups/#comments</comments><author>Drew McLellan</author><source url="http://carsonified.com/feed/">Carsonified</source><ng:postId>10359713989</ng:postId><ng:feedId>1729999</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>ABingo: An A/B Testing Plugin for Rails</title><link>http://feedproxy.google.com/~r/RailsInside/~3/hHoULIy7RcU/303-abingo-an-ab-testing-plugin-for-rails.html</link><description>&lt;p&gt;&lt;img src="http://www.railsinside.com/wp-content/uploads/2009/08/abingo.png" width="175" height="90" alt="abingo.png" style="float:right; margin-bottom:12px; margin-left:12px;" /&gt; &lt;a href="http://www.bingocardcreator.com/abingo/"&gt;ABingo&lt;/a&gt; is an &amp;#034;A/B testing&amp;#034; plugin to use on your Rails applications in order to test differences between two ways of showing the same information. It was developed by Patrick McKenzie, known mainly in the developer community as the creator of &lt;a href="http://www.bingocardcreator.com/"&gt;Bingo Card Creator&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;a href="http://en.wikipedia.org/wiki/A/B_testing"&gt;A/B testing&lt;/a&gt;&lt;/i&gt; (also known as &lt;i&gt;split testing&lt;/i&gt;) is a system of having two versions (or sometimes more) of a Web page and then showing them randomly to visitors, then comparing what visitors to different versions of the page do. This allows you to see if something as simple as a headline change or as complex as a total redesign has an effect on what user&amp;#039;s do - such as purchase your product or signup for your service. Once the &amp;#034;best&amp;#034; version has been determined, you can then continue to do further A/B tests until you run out of things to try, thus resulting in a better page.&lt;/p&gt;
&lt;p&gt;ABingo adds helpers to Rails to make it easy to implement A/B testing in your views and controllers:&lt;/p&gt;
&lt;pre&gt;&lt;span class="comment"&gt;# Simple syntax to start a test&lt;/span&gt;
&lt;span class="punct"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="ident"&gt;ab_test&lt;/span&gt;&lt;span class="punct"&gt;(&amp;#034;&lt;/span&gt;&lt;span class="string"&gt;login_button_test&lt;/span&gt;&lt;span class="punct"&gt;&amp;#034;,&lt;/span&gt; &lt;span class="punct"&gt;["&lt;/span&gt;&lt;span class="string"&gt;/images/button1.jpg&lt;/span&gt;&lt;span class="punct"&gt;",&lt;/span&gt; &lt;span class="punct"&gt;"&lt;/span&gt;&lt;span class="string"&gt;/images/button2.jpg&lt;/span&gt;&lt;span class="punct"&gt;"])&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;button_file&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;%&gt;&lt;/span&gt;&lt;span class="string"&gt;
&amp;lt;%= img_tag(button_file, :alt =&lt;/span&gt;&lt;span class="punct"&gt;&gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;#034;&lt;/span&gt;&lt;span class="string"&gt;Login!&lt;/span&gt;&lt;span class="punct"&gt;&amp;#034;)&lt;/span&gt; &lt;span class="punct"&gt;%&gt;&lt;/span&gt;&lt;span class="string"&gt;
&lt;% end %&lt;/span&gt;&lt;span class="punct"&gt;&gt;&lt;/span&gt;

&lt;span class="comment"&gt;# Track any arbitrary event as a conversion&lt;/span&gt;
&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;login&lt;/span&gt;
  &lt;span class="comment"&gt;# Business logic goes here&lt;/span&gt;
  &lt;span class="ident"&gt;bingo!&lt;/span&gt;&lt;span class="punct"&gt;(&amp;#034;&lt;/span&gt;&lt;span class="string"&gt;login_button_test&lt;/span&gt;&lt;span class="punct"&gt;&amp;#034;)&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/pre&gt;
&lt;p style="background-color:#ffd;padding:8px;font-family:verdana;font-size:12px"&gt;&lt;img src="http://www.rubyinside.com/wp-content/uploads/2009/07/jslab.png" width="32" height="35" alt="jslab.png" style="float:right; margin-left:12px; border:1px #000000 solid;" /&gt;&lt;a href="http://jumpstartlab.com" rel="nofollow"&gt;Jumpstart Lab&lt;/a&gt; is running a &lt;a href="http://jumpstartlab.com/courses/javascript/" rel="nofollow"&gt;&lt;strong&gt;JavaScript Master Class&lt;/strong&gt;&lt;/a&gt; for Javascript &amp;amp; UI programmers with &lt;a href="http://mir.aculo.us/"&gt;Thomas Fuchs&lt;/a&gt; (Scriptaculous, Prototype Core) and &lt;a href="http://slash7.com/"&gt;Amy Hoy&lt;/a&gt; (UI Expert) on 9/12 in Washington, DC. Save 10% with code &amp;#034;rubyinside&amp;#034;!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/RailsInside?a=hHoULIy7RcU:KtDYJcyGCW4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RailsInside?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RailsInside?a=hHoULIy7RcU:KtDYJcyGCW4:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RailsInside?i=hHoULIy7RcU:KtDYJcyGCW4:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RailsInside?a=hHoULIy7RcU:KtDYJcyGCW4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RailsInside?i=hHoULIy7RcU:KtDYJcyGCW4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RailsInside?a=hHoULIy7RcU:KtDYJcyGCW4:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RailsInside?i=hHoULIy7RcU:KtDYJcyGCW4:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/RailsInside?a=hHoULIy7RcU:KtDYJcyGCW4:3H-1DwQop_U"&gt;&lt;img src="http://feeds.feedburner.com/~ff/RailsInside?i=hHoULIy7RcU:KtDYJcyGCW4:3H-1DwQop_U" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/RailsInside/~4/hHoULIy7RcU" height="1" width="1"/&gt;</description><pubDate>Wed, 19 Aug 2009 18:21:08 GMT</pubDate><guid isPermaLink="false">http://www.railsinside.com/plugins/303-abingo-an-ab-testing-plugin-for-rails.html</guid><comments>http://www.railsinside.com/plugins/303-abingo-an-ab-testing-plugin-for-rails.html#comments</comments><author>Peter Cooper</author><source url="http://feeds.feedburner.com/RailsInside">Rails Inside</source><ng:postId>10360298379</ng:postId><ng:feedId>2951405</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>Startup panel review</title><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/ADM8c1eIhCM/166066174</link><description>&lt;h2&gt;Panelists&lt;/h2&gt;

&lt;p&gt;Last night’s startup panel included representatives from self-funded (thoughtbot), angel funded (&lt;a href="http://oneforty.com"&gt;oneforty&lt;/a&gt;), and Series A and Series B funded companies (&lt;a href="http://panjiva.com"&gt;Panjiva&lt;/a&gt; and &lt;a href="http://zendesk.com"&gt;Zendesk&lt;/a&gt;). All four companies are using Ruby in some form.&lt;/p&gt;

&lt;p&gt;While many topics were addressed, such as why each company uses Rails, how they developed their products, how they hire, and how they secured funding, there was a common theme to every topic.&lt;/p&gt;

&lt;h2&gt;People are the most important part of a startup&lt;/h2&gt;

&lt;p&gt;The following quotes are paraphrased from memory and &lt;a href="http://is.gd/2mPrK"&gt;Josh Nichols’ notes&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;“Investors aren’t interested in Ruby; They’re interested in startups.” - Jim Psota, Panjiva&lt;/blockquote&gt;

&lt;blockquote&gt;“The most important effect of publishing open source code for us has been attracting great employees.” - Matt Jankowski, thoughtbot&lt;/blockquote&gt;

&lt;blockquote&gt;“The best people want to be part of something big so as a founder, you need to articulate the vision and communicate why it makes sense to job candidates.” - Jim&lt;/blockquote&gt;

&lt;blockquote&gt;“The great secret of startups is every day you’re doing something for the first time so the most important quality we look for is ability to learn quickly.” - Jim&lt;/blockquote&gt;

&lt;blockquote&gt;“We secured our angel round through networking. They then introduced us to the right people for later rounds.” - Jim&lt;/blockquote&gt;

&lt;blockquote&gt;“We were initially self-funded, then raised enough from friends and family, offering 1% portions of the company for cheap, to allow us to work on the product full time.” - Morten Primdahl, Zendesk&lt;/blockquote&gt;

&lt;blockquote&gt;“When you pitch an investor, be very honest. Say, ‘These are the things I know, and these are the things we don’t know. Here are our current hypotheses on the things we don’t know which we need to experiment on.’” - Jim&lt;/blockquote&gt;

&lt;blockquote&gt;“We secured angel funding due to the strength of our founder’s network. She knew or found the right investors for our type of business.” - Mike Champion, oneforty&lt;/blockquote&gt;

&lt;blockquote&gt;“It’s a positive to structure your team like Lincoln’s ‘team of rivals.’ Contrarian views questioning the status quo are necessary from inside the organization.” - Jim&lt;/blockquote&gt;

&lt;h2&gt;Comprehensive notes&lt;/h2&gt;

&lt;p&gt;If you’re interested in reading more about the tools, techniques, and technologies each companies use, read Josh Nichols’ comprehensive notes, which are &lt;a href="http://is.gd/2mPrK"&gt;available here&lt;/a&gt;.&lt;/p&gt;</description><pubDate>Tue, 18 Aug 2009 23:54:54 GMT</pubDate><guid isPermaLink="false">http://robots.thoughtbot.com/post/166066174</guid><source url="http://feeds.feedburner.com/GiantRobotsSmashingIntoOtherGiantRobots">GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS</source><ng:postId>10355078245</ng:postId><ng:feedId>1135803</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>TuneUp your iTunes collection</title><link>http://feedproxy.google.com/~r/unclutterer/~3/KXT-jutdKgQ/</link><description>&lt;p&gt;&lt;img src="http://unclutterer.com/wp-content/uploads/090818-cleaner.jpg" align="right" class="thumb-right"&gt;I use &lt;a href="http://www.apple.com/itunes/"&gt;iTunes&lt;/a&gt; to organize my digital music collection and, for the most part, it suits my needs. I say &amp;#8220;for the most part&amp;#8221; because similar to the problem I&amp;#8217;ve been having with the &lt;a href="http://unclutterer.com/2009/07/28/print-photographs-have-been-scanned-now-what/"&gt;photographs that I had scanned&lt;/a&gt;, not all of my music has correct information associated with it. Fortunately for my music, though, I don&amp;#8217;t have to go through my entire iTunes collection song-by-song to straighten out the missing and incorrect data. I have found a program that simply corrects my data &amp;#8212; &lt;a href="http://www.tuneupmedia.com/index"&gt;TuneUp&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Based on algorithms and other technical things I don&amp;#8217;t fully understand (kind of like the iPhone app &lt;a href="http://www.shazam.com/music/web/pages/iphone.html"&gt;Shazam&lt;/a&gt;), TuneUp picks up where iTunes leaves off at properly identifying the music in my collection. I no longer have seven Track 03s on my playlists. All I have to do is drag the misidentified song into the &amp;#8220;cleaner&amp;#8221; and TuneUp pulls up possible matches. (The cleaner function is displayed at right.)&lt;/p&gt;
&lt;p&gt;In addition to identifying songs, it also fixes formatting, finds rarer cover art, matches artist names, and even gives information about the songs in your collection sort of like VH1&amp;#8217;s old &lt;a href="http://en.wikipedia.org/wiki/Pop-up_Video"&gt;Pop-Up Videos&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are other programs out there similar to TuneUp, I just happened to find this program first and since it worked for me I didn&amp;#8217;t try the others. If you have tried other programs and had success, please tell us about your experiences in the comments. TuneUp is free for a &amp;#8220;limited-access&amp;#8221; download, and is around $20 for an &amp;#8220;unlimited&amp;#8221; version.&lt;/p&gt;
&lt;p&gt;If only I could find a program to clean up my digital photographs as easily &amp;#8230;&lt;/p&gt;
&lt;p&gt;(&lt;em&gt;Image from &lt;a href="http://www.tuneupmedia.com/index"&gt;TuneUp&amp;#8217;s&lt;/a&gt; website &amp;#8230; I fear if I show my music collection you all will make strange &amp;#8212; but probably correct &amp;#8212; assumptions about me! And, it should go without saying, but I wasn&amp;#8217;t paid to write this review.&lt;/em&gt;)&lt;/p&gt;
&lt;img src="http://unclutterer.com/?ak_action=api_record_view&amp;id=6321&amp;type=feed" alt="" /&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/BOnz--MAf_X57DiUV2Yc6xQE-Bw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BOnz--MAf_X57DiUV2Yc6xQE-Bw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/BOnz--MAf_X57DiUV2Yc6xQE-Bw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BOnz--MAf_X57DiUV2Yc6xQE-Bw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/unclutterer?a=KXT-jutdKgQ:G03QTadT7Q0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/unclutterer?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/unclutterer?a=KXT-jutdKgQ:G03QTadT7Q0:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/~ff/unclutterer?d=dnMXMwOfBR0" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/unclutterer?a=KXT-jutdKgQ:G03QTadT7Q0:wF9xT3WuBAs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/unclutterer?i=KXT-jutdKgQ:G03QTadT7Q0:wF9xT3WuBAs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/unclutterer?a=KXT-jutdKgQ:G03QTadT7Q0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/unclutterer?i=KXT-jutdKgQ:G03QTadT7Q0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/unclutterer?a=KXT-jutdKgQ:G03QTadT7Q0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/unclutterer?i=KXT-jutdKgQ:G03QTadT7Q0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/unclutterer?a=KXT-jutdKgQ:G03QTadT7Q0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/unclutterer?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;</description><pubDate>Tue, 18 Aug 2009 11:30:00 GMT</pubDate><guid isPermaLink="false">http://unclutterer.com/?p=6321</guid><comments>http://unclutterer.com/2009/08/18/tuneup-your-itunes-collection/#comments</comments><author>Erin Doland</author><source url="http://feeds.feedburner.com/unclutterer">Unclutterer</source><ng:postId>10351560183</ng:postId><ng:feedId>1358261</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>JavaScript MVC</title><link>http://www.alistapart.com/articles/javascript-mvc/</link><description>As JavaScript takes center stage in our web applications, we need to produce ever more modular code. MVC (Model-View-Controller) may hold the key. MVC is a design pattern that breaks an application into three parts: the data (Model), the presentation of that data to the user (View), and the actions taken on any user interaction (Controller). Discover how MVC can make the JavaScript that powers your web applications more reusable and easier to maintain.</description><pubDate>Tue, 18 Aug 2009 09:00:38 GMT</pubDate><guid isPermaLink="false">http://www.alistapart.com/articles/javascript-mvc/</guid><author>contact.us@alistapart.com (Jonathan Snook)</author><source url="http://www.alistapart.com/site/rss">A List Apart</source><ng:postId>10351271142</ng:postId><ng:feedId>888</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>Parallel processing in ruby made simple</title><link>http://feedproxy.google.com/~r/Rubyflow/~3/MjMAhmHb__4/2635</link><description>&lt;a href="http://github.com/grosser/parallel/tree/master"&gt;Parallel processing for ruby&lt;/a&gt; allows to easily run any code in parallel Processes or Threads , no more piping/forking/serialisation knowledge required, just  &lt;code&gt;results = Parallel.in_processes(2){|i| expensive_computation(data[i]) }&lt;/code&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Rubyflow?a=MjMAhmHb__4:w7abm7hRZg0:3H-1DwQop_U"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rubyflow?i=MjMAhmHb__4:w7abm7hRZg0:3H-1DwQop_U" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rubyflow/~4/MjMAhmHb__4" height="1" width="1"/&gt;</description><pubDate>Sun, 16 Aug 2009 17:04:43 GMT</pubDate><guid isPermaLink="false">http://www.rubyflow.com/items/2635</guid><source url="http://feeds.feedburner.com/Rubyflow?format=xml">RubyFlow</source><ng:postId>10341385056</ng:postId><ng:feedId>2593439</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>Rails requests missing the HTTP body</title><link>http://pivotallabs.com/users/amilligan/blog/articles/979-rails-requests-missing-the-http-body</link><description>&lt;p&gt;This is a bug in Rails that quite likely affects you, but which you've even more likely never experienced.  I've posted it here for the benefit of the small number of people who will run into this problem and turn to Google for help.&lt;/p&gt;

&lt;p&gt;In short, if you use Mongrel app servers &amp;#40;this may affect Passenger as well, I don't know&amp;#41;, the first HTTP request to your Rails app after you restart your servers, or otherwise reload your environment, will have an empty HTTP body.&lt;/p&gt;

&lt;p&gt;I say you've likely never experienced this because the majority of HTTP requests to your Rails app are likely GET requests, which always have empty HTTP bodies.  After that first request everything will work just fine.  Even if you're unlucky enough to receive a POST or a PUT request containing a body immediately after restart it will only fail once, which you could easily write off an an anomaly.  You also won't see this behavior in your development environment, or any environment in which you use Mongrel as a web server rather than just an app server.&lt;/p&gt;

&lt;p&gt;If you're interested in a patch for the bug, I've submitted one to Rails &lt;a href="https://rails.lighthouseapp.com/projects/8994/tickets/2993-first-request-will-always-have-an-empty-body-due-to-delayed-load-of-action_controllercgi_process"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;The source of the problem lies in how ActionController initializes itself.  In the actionpack gem you'll find the lib/action_controller/cgi_ext.rb file, which does little more than load the three files in the cgi_ext directory:&lt;/p&gt;

&lt;pre&gt;
require 'action_controller/cgi_ext/stdinput'
require 'action_controller/cgi_ext/query_extension'
require 'action_controller/cgi_ext/cookie'
...
&lt;/pre&gt;

&lt;p&gt;The cgi_ext/query_extension.rb file is the interesting one:&lt;/p&gt;

&lt;pre&gt;
require 'cgi'

class CGI #:nodoc:
  module QueryExtension
    # Remove the old initialize_query method before redefining it.
    remove_method :initialize_query

    # Neuter CGI parameter parsing.
    def initialize_query
      # Fix some strange request environments.
      env_table['REQUEST_METHOD'] ||= 'GET'

      # POST assumes missing Content-Type is application/x-www-form-urlencoded.
      if env_table['CONTENT_TYPE'].blank? &amp;amp;&amp;amp; env_table['REQUEST_METHOD'] == 'POST'
        env_table['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'
      end

      @cookies = CGI::Cookie::parse&amp;#40;env_table['HTTP_COOKIE'] || env_table['COOKIE']&amp;#41;
      @params = {}
    end
  end
end
&lt;/pre&gt;

&lt;p&gt;This replaces the default #initialize_query method provided by Ruby's CGI library:&lt;/p&gt;

&lt;pre&gt;
    def initialize_query&amp;#40;&amp;#41;
      if &amp;#40;&amp;quot;POST&amp;quot; == env_table['REQUEST_METHOD']&amp;#41; and
         r|\Amultipart/form-data.*boundary=\&amp;quot;?&amp;#40;[^\&amp;quot;;,]+&amp;#41;\&amp;quot;?|n.match&amp;#40;env_table['CONTENT_TYPE']&amp;#41;
        boundary = $1.dup
        @multipart = true
        @params = read_multipart&amp;#40;boundary, Integer&amp;#40;env_table['CONTENT_LENGTH']&amp;#41;&amp;#41;
      else
        @multipart = false
        @params = CGI::parse&amp;#40;
                    case env_table['REQUEST_METHOD']
                    when &amp;quot;GET&amp;quot;, &amp;quot;HEAD&amp;quot;
                      if defined?&amp;#40;MOD_RUBY&amp;#41;
                        Apache::request.args or &amp;quot;&amp;quot;
                      else
                        env_table['QUERY_STRING'] or &amp;quot;&amp;quot;
                      end
                    when &amp;quot;POST&amp;quot;
                      stdinput.binmode if defined? stdinput.binmode
# =====&amp;gt;              stdinput.read&amp;#40;Integer&amp;#40;env_table['CONTENT_LENGTH']&amp;#41;&amp;#41; or ''
                    else
                      read_from_cmdline
                    end
                  &amp;#41;
      end

      @cookies = CGI::Cookie::parse&amp;#40;&amp;#40;env_table['HTTP_COOKIE'] or env_table['COOKIE']&amp;#41;&amp;#41;
    end
&lt;/pre&gt;

&lt;p&gt;The interesting line is the one I've marked with a comment rocket.  Notice how it reads from stdinput; this leaves the read pointer at the &lt;em&gt;end&lt;/em&gt; of the input stream.  Now look back at the Rails override for this method, and notice how it does &lt;em&gt;not&lt;/em&gt; read from stdinput, thus leaving the read pointer at the &lt;em&gt;start&lt;/em&gt; of the input stream.&lt;/p&gt;

&lt;p&gt;This is all fine and dandy as long as all of the ActionController code loads up and patches the CGI library properly.  However, ActionController doesn't load the cgi_ext.rb file &amp;#40;or its dependencies&amp;#41; until it references either the CgiRequest or CGIHandler classes &amp;#40;which require cgi_process.rb, which require cgi_ext.rb&amp;#41;, as part of the first request, which is &lt;em&gt;after&lt;/em&gt; the default Ruby CGI library has read the input stream containing the request body.  ActionController then tries to read the request body assuming the read pointer is at the start of the stream.  Oops.  Subsequent requests work fine, because everything has now been loaded.&lt;/p&gt;

&lt;p&gt;Finding the source of this bug took some doing &amp;#40;&lt;a href="http://pivotallabs.com/users/cheister/blog"&gt;Chris Heisterkamp, aka "The Hammer"&lt;/a&gt; and I tracked it down together&amp;#41;, but the fix is easy.  If you look at the &lt;a href="https://rails.lighthouseapp.com/projects/8994/tickets/2993-first-request-will-always-have-an-empty-body-due-to-delayed-load-of-action_controllercgi_process"&gt;patch&lt;/a&gt; you'll see it's simply a single require in action_controller.rb.  You can achieve the same result by requiring 'action_controller/cgi_ext' in an initializer file in your app.&lt;/p&gt;

&lt;p&gt;Like many problems, this one should go away in Rails 3.  Rails has deprecated use of the CGI library, and the CGI extensions have already been removed from the Rails master branch.  However, it's a real problem now, and will remain so for at least some amount of time.&lt;/p&gt;</description><pubDate>Sat, 15 Aug 2009 20:56:00 GMT</pubDate><guid isPermaLink="false">http://pivotallabs.com/users/amilligan/blog/articles/979-rails-requests-missing-the-http-body</guid><author>Adam Milligan</author><source url="http://feeds.feedburner.com/pivotallabs/blabs.atom">Pivotal Blabs</source><ng:postId>10337987927</ng:postId><ng:feedId>1320530</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>Hostname middleware</title><link>http://feedproxy.google.com/~r/Rubyflow/~3/UOeUBDqKFXA/2634</link><description>&lt;a href="http://gravityblast.com/2009/08/15/hostname-middleware-for-rails-apps-on-multiple-servers/"&gt;How to&lt;/a&gt; know which server has sent back the response during development with multiple servers behind a load balancer.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Rubyflow?a=UOeUBDqKFXA:N0K7SjJ6X7Y:3H-1DwQop_U"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Rubyflow?i=UOeUBDqKFXA:N0K7SjJ6X7Y:3H-1DwQop_U" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Rubyflow/~4/UOeUBDqKFXA" height="1" width="1"/&gt;</description><pubDate>Sat, 15 Aug 2009 22:58:11 GMT</pubDate><guid isPermaLink="false">http://www.rubyflow.com/items/2634</guid><source url="http://feeds.feedburner.com/Rubyflow?format=xml">RubyFlow</source><ng:postId>10338288209</ng:postId><ng:feedId>2593439</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>A grand piano for your violin</title><link>http://feedproxy.google.com/~r/GiantRobotsSmashingIntoOtherGiantRobots/~3/0tnIU8q5YXw/163627511</link><description>&lt;h2&gt;Database indexes&lt;/h2&gt;

&lt;p&gt;What are database indexes?  If you’re building web apps powered by a relational database, you should know.&lt;/p&gt;

&lt;p&gt;A database index is a data structure in the database which improves the speed of operations (typically row lookups) on a database table, or across tables.  Think of it like the index of a book.  If you’re reading a book about the Wu Tang Clan and you want to find all the Method Man references, it’d be a lot easier to flip to the index and find “Method Man”, then open up directly to all those pages numbers (as opposed to scanning every page of the book for the words “Method Man”), wouldn’t it?&lt;/p&gt;

&lt;p&gt;Well that’s basically how database indexes work.  Assuming you have an indexed &lt;code&gt;users.id&lt;/code&gt; column on your users table, when you query a database with…&lt;/p&gt;

&lt;p&gt;&lt;code&gt;SELECT name FROM users WHERE id = 1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;…the database can find that row very quickly, rather than having to scan through every row in the table and check whether it’s “id” value is equal to 1.&lt;/p&gt;

&lt;p&gt;So, in a typical rails application, what things should you index?&lt;/p&gt;

&lt;h2&gt;Primary keys&lt;/h2&gt;

&lt;p&gt;Most SQL databases with the concept of a primary key will automatically create an index on the primary key column when it exists.  In Rails, this is typically the “id” column in a table, and because Rails tells the DB that it’s a primary key, you’ll get the index “for free”, created by the database.  This is very important for a “show view” like /users/1, for example.  The request comes in, and the query to “find user with id equal to 1” occurs very quickly because the &lt;code&gt;users.id&lt;/code&gt; column is indexed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Best practice: index every primary key&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Foreign keys&lt;/h2&gt;

&lt;p&gt;Now what if that user has_many comments?  In Rails, you most likely have a user_id column in your comments table, which the &lt;code&gt;Comment&lt;/code&gt; model will use to determine the user that it belongs to.  You should have an index on every foreign key column.  When you make a page like /users/1/comments, two things need to happen.  First, we lookup the user with id equal to 1.  Assuming we’ve indexed primary keys, this will be fast.  Second, we want to find all comments that belong to this user.  If we’ve indexed &lt;code&gt;comments.user_id&lt;/code&gt;, this will be fast too.&lt;/p&gt;

&lt;p&gt;We’ve actually taken this to a “policy” point where we try to avoid ever naming a column with an “_id” suffix, unless it is an integer foreign key column that needs to be indexed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Best practice: index every foreign key column&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Columns used by to_param&lt;/h2&gt;

&lt;p&gt;Let’s say you’ve got indexes in place on users.id and comments.user_id, but then a request comes in to make “pretty urls” on these pages.  Ok, no problem.  We add a &lt;code&gt;users.keyword&lt;/code&gt; column to users, and allow users to specify a username with their account.  Now we can make requests to urls like /users/matt/comments, and see all comments by that user.  Well, same situation as before, we need to do a find, but this time we’re matching against the ‘keyword’ column and not the ‘id’ column, so this needs to be indexed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Best practice: index every column used in a WHERE clause&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Composite keys on join models&lt;/h2&gt;

&lt;p&gt;What if multiple users could write one comment together, and we needed to store a timestamp to know &lt;em&gt;when&lt;/em&gt; each of them last edited the comment?  We could introduce a &lt;code&gt;Commentary&lt;/code&gt; join model, which would connect users to comments.  This model would have a user_id and comment_id column, along with a last_edited_at timestamp, or something.&lt;/p&gt;

&lt;p&gt;In this case, there should be a composite index (an index across multiple columns, basically) on the (user_id, comment_id) combination on this join model.  That way, when we run a query to find all comments that a certain user has been an editor on, we can quickly those comments through the join table.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Best practice: index composite keys on join models&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;State columns&lt;/h2&gt;

&lt;p&gt;What if comments can be in “Draft” (not done yet), “Submitted” (done, awaiting approval), “Published” (approved) or “Unpublished” (approved then taken down) states?  We’re most likely going to have an interface for users which shows “all of your draft comments” so that they can resume working on them, and “all your submitted comments” so they can review their past wisdom.&lt;/p&gt;

&lt;p&gt;In this case, we’ll add a &lt;code&gt;comments.publication_state&lt;/code&gt; column to comments (I have an unfounded fear of using ‘state’ as a column name; sounds like a reserved word to me, but it’s not!), which will be a varchar column and hold one of those states as a string.  We should index that column so that the queries to find comments in a certain state are fast.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Best practice: index every varchar/string column that’s used for storing state&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Boolean columns&lt;/h2&gt;

&lt;p&gt;Well, with the introduction of the “submit for approval” concept we also need to add an “admin” concept for users, with the option to either be an admin or not be an admin.  We need a “all users who are admins” view so that we can see at a glance who is doing comment approval and click through to see what they’ve approved.&lt;/p&gt;

&lt;p&gt;In this case, we’ll add a boolean column called ‘admin’ to the users table (in mysql, this is implemented with a TINYINT column, may be different elsewhere).  This column should be indexed, so that the query to find all admin users is fast.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Best practice: index every boolean column&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Datetime columns&lt;/h2&gt;

&lt;p&gt;As this commenting application enjoys continued success, we’ve decided that viewing comments in the order in which they were posted would really improve our users’ ability to find what they were looking for.  To do this, we’ll add an order by clause to the query that gets the comments for them to view.&lt;/p&gt;

&lt;p&gt;To keep this performant, we should add an index to the ‘created_at’ column on comments.  If we had a view sorting by published_at or updated_at, we’d want to index that as well.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Best practice: index every datetime column&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Columns used in polymorphic conditional joins&lt;/h2&gt;

&lt;p&gt;In Rails when you establish a polymorphic relationship you end up with a condition on a join in the resulting query.  For example, let’s say you can apply a &lt;code&gt;Tag&lt;/code&gt; to a &lt;code&gt;Comment&lt;/code&gt; via a &lt;code&gt;Tagging&lt;/code&gt; association.  There will be queries like:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
SELECT * FROM comments
INNER JOIN taggings
ON taggings.taggable_type = 'Comment' and taggings.taggable_id = '3'
INNER JOIN tags on taggings.tag_id = tags.id
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In this case, you should add a composite index to taggings(taggable_type, taggable_id) pair, so that the initial lookup goes well.  You should also have already indexed taggings(tag_id) because this is a foreign key association.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Best practice: index all _type/_id pairs on polymorphic join tables&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Columns used in validations&lt;/h2&gt;

&lt;p&gt;Nine times out of ten you probably already have this covered by following the best practices already enumerated in this post, but another thing to watch out for are Rails data validations on models.  If you have a column which has a uniqueness constraint, for example, every time you save a record of that class (regardless of whether that particular column has changed or not), ActiveRecord is going to run a query to try to find other rows which have the same data in that column.  It will be much faster to do this comparison on indexed columns than non-indexed columns.&lt;/p&gt;

&lt;p&gt;An example of this would be something like a &lt;code&gt;users.email&lt;/code&gt; column, where the email had to be unique across all user rows in the table.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Best practice: index all columns that will generate queries from model validations&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;Columns used for STI&lt;/h2&gt;

&lt;p&gt;With the &lt;a href="http://martinfowler.com/eaaCatalog/singleTableInheritance.html"&gt;Single Table Inheritance&lt;/a&gt; pattern in Active Record, there is a ‘type’ column created to store the parent class of a subclass.  For example, if &lt;code&gt;FancyGroup&lt;/code&gt; inherits from &lt;code&gt;Group&lt;/code&gt; with STI, there will be groups table with a ‘type’ column, which all &lt;code&gt;FancyGroup&lt;/code&gt; records will populate with the “FancyGroup” string, to indicate that those records are of that subclass.&lt;/p&gt;

&lt;p&gt;This means that every query which looks up &lt;code&gt;FancyGroup&lt;/code&gt; records is going to have at least a &lt;code&gt;WHERE groups.type = 'FancyGroup'&lt;/code&gt; clause in it, and that means that the ‘type’ column on that table should be indexed.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Best practice: index all ‘type’ columns on tables used for STI&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;How to add an index&lt;/h2&gt;

&lt;p&gt;In Rails, adding an index is really straightforward.  Here’s an example from a recent application where I was converting what was previously a numeric lookup to be a “pretty url” lookup, and wanted something like /products/thirty-six-chambers instead of /products/123…&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
class AddIndexToProductsKeyword &lt; ActiveRecord::Migration
  def self.up
    add_index :products, :keyword
  end
  def self.down
    remove_index :products, :keyword
  end
end
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;products.keyword&lt;/code&gt; column already existed in this case, it was just a matter of adding an index to that column.  The Rails guides site has more about &lt;a href="http://guide.rails.info/migrations.html"&gt;Rails Migrations&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To add a composite index (an index across multiple columns), Rails uses an Array syntax.  Here’s an example for the earlier &lt;code&gt;Tagging&lt;/code&gt; scenario:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;
class AddIndicesToAllPolymorphicTables &lt; ActiveRecord::Migration
  def self.up
    add_index :taggings, [:taggable_type, :taggable_id]
  end
  def self.down
    remove_index :taggings, :column =&gt; [:taggable_type, :taggable_id]
  end
end
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Side note - the pattern by which Rails generates &lt;em&gt;names&lt;/em&gt; for indexes has changed over time.  In earlier versions of rails, for example, the table name was prefixed onto the index name, creating names like “posts_published_index”.  In more recent versions, the same migration would generate an index named “index_posts_on_published”.  If you are starting a new application, you can probably afford to not care about this at all.  If you are updating a legacy application which added indexes to your production database using the old naming, be careful about how you add/remove/rename indexes, so that local developer environments don’t wind up out of sync with the production environment.&lt;/p&gt;

&lt;h2&gt;But I don’t have that much data…&lt;/h2&gt;

&lt;p&gt;Contrary to developer myth, database indexes are not “just for speed” (they are technically for speed, but they are for achieving it in the first place, not fixing problems), or only meant to be used once your data reaches a certain size, or a case of premature optimization.  Sure, maybe you’ll get away with decent performance on your local database running in development mode with you as the only user, but that’s not the real use case for the application, is it?  Database indexes are not tools to troubleshoot speed problems or data growing pains - &lt;strong&gt;they’re a fundamental tool that relational databases use to function correctly in the first place&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;What about search?&lt;/h2&gt;

&lt;p&gt;This post doesn’t cover doing full text search against string and text fields, perhaps a future post will.  That being said, basically everything in this post will likely assist in speeding up any query that is doing search, by virtue of speeding up the joins and ordering and state restrictions that may be included in a search query.&lt;/p&gt;

&lt;h2&gt;Ok, so this gets me like a 5% speed increase, right?  Who cares.&lt;/h2&gt;

&lt;p&gt;Totally wrong.  It’s hard to put an average on the speed increase, because it depends on the schema and the query.  But that’s not the point.  If you’re not properly indexing the columns in the database and making sure your queries are using them, you’re not using the tool correctly.&lt;/p&gt;

&lt;p&gt;For the sake of example - it’s not too out of the ordinary to see a non-indexed query that takes 1 minute or more to complete drop down to the tenths or hundredths of a second in length once it’s been made to use proper indexes.  It’s a BIG DEAL.  Run your own tests if you don’t believe me.  Have someone else run tests for you if you don’t know how to run tests.  Just take my word for it if you don’t know anyone competent enough to run tests for you.&lt;/p&gt;

&lt;h2&gt;What’s the downside&lt;/h2&gt;

&lt;p&gt;Well, there’s no “catch”, other than needing to remember to do this regularly.  There are two “downsides” to indexing.&lt;/p&gt;

&lt;p&gt;First, if you haven’t introduced indexes from day one, or you are adding an index to a new column in a table with many rows, the migration can take quite a bit of time.  For example, when we passed about 12 million rows in the “messages” table in &lt;a href="http://thunderthimble.com"&gt;Thunder Thimble&lt;/a&gt;, we started experiencing some sluggishness on a certain query, and found that indexing a previously unindexed column was necessary to get things snappy again.  Running that migration on the 12 million row table took about 7 hours, and the bulk of that time was spent adding the index.&lt;/p&gt;

&lt;p&gt;Second, you can’t just go about willy nilly and add database indexes to EVERY column in every table in your database.  There &lt;em&gt;is a cost&lt;/em&gt; to the database to &lt;em&gt;maintain&lt;/em&gt; those indexes, and every time an INSERT or UPDATE occurs, there is work to be done that would not need to be done without the index in place.  In most scenarios, this is more of a theoretical fear than a practical fear, but definitely do your homework on it before you go index crazy.&lt;/p&gt;

&lt;h2&gt;How about some brunch?&lt;/h2&gt;

&lt;p&gt;Adding database indexes to migrations when you should, and doing regular database schema reviews to look for missing indexes is part of any applications healthy breakfast.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Index_(database)"&gt;Database Indexes on wikipedia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://20bits.com/articles/interview-questions-database-indexes/"&gt;20bits interview on database indexes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html"&gt;How mySQL uses indexes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://weblog.jamisbuck.org/2006/10/23/indexing-for-db-performance"&gt;Jamis Buck explains indexing databases&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is a “rake db:indexes:missing” task (which identifies missing foreign key indexes) in our &lt;a href="http://github.com/thoughtbot/limerick_rake/tree/master"&gt;limerick rake&lt;/a&gt; plugin, for those inclined to make it part of their breakfast too.&lt;/p&gt;

&lt;p&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/j0qm0KUPeD8&amp;hl=en&amp;fs=1&amp;"&gt;
&lt;param name="allowFullScreen" value="true"&gt;
&lt;param name="allowscriptaccess" value="always"&gt;
&lt;embed src="http://www.youtube.com/v/j0qm0KUPeD8&amp;hl=en&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;</description><pubDate>Sat, 15 Aug 2009 18:00:54 GMT</pubDate><guid isPermaLink="false">http://robots.thoughtbot.com/post/163627511</guid><source url="http://feeds.feedburner.com/GiantRobotsSmashingIntoOtherGiantRobots">GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS</source><ng:postId>10337527757</ng:postId><ng:feedId>1135803</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item><item><title>FatSecret Looks To Become A Central Hub For Nutrition Data With New API</title><link>http://feedproxy.google.com/~r/Techcrunch/~3/ofaYTCuz5lA/</link><description>&lt;blockquote&gt;Shared by  Ryan Sholin 
&lt;br&gt;
This is actually something I think we need: An API for nutritional data.&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="http://cache0.techcrunch.com/wp-content/uploads/2009/08/fatsecretshot.png"&gt;&lt;a href="http://www.fatsecret.com"&gt;FatSecret&lt;/a&gt;, an Australian social network focused on nutrition and weight loss that we &lt;a href="http://www.techcrunch.com/2007/04/29/fatsecret-for-fat-people-who-want-to-be-less-so/"&gt;covered&lt;/a&gt; back in 2007, is launching a new API tonight that allows third party sites and services to tap into its database of nutritional data, excercise information, and other health stats.  You can access the new FatSecret Platform &lt;a href="http://platform.fatsecret.com/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;CEO Rodney Moses says that FatSecret is allowing developers to access the API for free, in the hopes of turning FatSecret into &lt;i&gt;the&lt;/i&gt; reliable and accurate resource for nutritional information.  He points out the fact that while there are plenty of diet sites on the web that contain nutrition info for various foods, much of the data is disjointed — there’s no established comprehensive source that people turn to first.  FatSecret hopes to become the authoritative hub for this kind of information.  The site has gathered its data from a number of publicly available resources like the USDA, and also has many user-submitted entries from users on its social network.  Moses says that all of the data has been curated to ensure accuracy.&lt;/p&gt;
&lt;p&gt;The other component to the new API is a brand utility, which invites food and beverage brand owners to submit their nutrition facts into the system so that they can be retrieved using the FatSecret API.&lt;/p&gt;
&lt;p&gt;Moses says that the site itself is still growing steadily, with half a million monthly visitors and around double that number when including users who access the site through other means, like its mobile applications.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Crunch Network&lt;/em&gt;&lt;/strong&gt;:  &lt;a href="http://www.crunchgear.com"&gt;CrunchGear&lt;/a&gt;&lt;em&gt; &lt;/em&gt;drool over the sexiest new gadgets and hardware.&lt;/p&gt;
&lt;div&gt;&lt;a href="http://d.techcrunch.com/ck.php?n=a8e452d3&amp;amp;cb=1858"&gt;&lt;img src="http://d.techcrunch.com/avw.php?zoneid=38&amp;amp;cb=557&amp;amp;n=a8e452d3" alt="" border="0"&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div&gt;&lt;a href="http://d.techcrunch.com/ck.php?n=a9e88cf5&amp;amp;cb=1756"&gt;&lt;img src="http://d.techcrunch.com/avw.php?zoneid=13&amp;amp;cb=621&amp;amp;n=a9e88cf5" alt="" border="0"&gt;&lt;/a&gt;&lt;/div&gt;

&lt;p&gt;&lt;iframe src="http://feedads.g.doubleclick.net/%7Eah/f/v7tfagih50mrtjprksjv4s1ftk/300/250?ca=1&amp;amp;fh=280#http%3A%2F%2Fwww.techcrunch.com%2F2009%2F08%2F14%2Ffatsecret-looks-to-become-a-central-hub-for-nutrition-data-with-new-api%2F" marginwidth="0" marginheight="0" frameborder="0" height="280" scrolling="no" width="100%"&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;div&gt;
&lt;a href="http://feeds.feedburner.com/%7Eff/Techcrunch?a=ofaYTCuz5lA:qA7xSIzv8GQ:2mJPEYqXBVI"&gt;&lt;img src="http://feeds.feedburner.com/%7Eff/Techcrunch?d=2mJPEYqXBVI" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/%7Eff/Techcrunch?a=ofaYTCuz5lA:qA7xSIzv8GQ:dnMXMwOfBR0"&gt;&lt;img src="http://feeds.feedburner.com/%7Eff/Techcrunch?d=dnMXMwOfBR0" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/%7Eff/Techcrunch?a=ofaYTCuz5lA:qA7xSIzv8GQ:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/%7Eff/Techcrunch?i=ofaYTCuz5lA:qA7xSIzv8GQ:D7DqB2pKExk" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/%7Eff/Techcrunch?a=ofaYTCuz5lA:qA7xSIzv8GQ:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/%7Eff/Techcrunch?d=7Q72WNTAKBA" border="0"&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/%7Eff/Techcrunch?a=ofaYTCuz5lA:qA7xSIzv8GQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/%7Eff/Techcrunch?d=yIl2AUoC8zA" border="0"&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/%7Er/Techcrunch/%7E4/ofaYTCuz5lA" height="1" width="1"&gt;
</description><pubDate>Fri, 14 Aug 2009 11:36:54 GMT</pubDate><guid isPermaLink="false">tag:google.com,2005:reader/item/82548234311be67f</guid><author>(author unknown)</author><source url="http://www.google.com/reader/public/atom/user/07803237709052972366/state/com.google/broadcast">Ryan Sholin's shared items in Google Reader</source><ng:postId>10334519428</ng:postId><ng:feedId>2792769</ng:feedId><ng:folderId>0</ng:folderId><ng:folder ng:id="0" ng:flagState="0" ng:annotation="" /></item></channel></rss>