<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Offermann.us</title>
	<atom:link href="http://offermann.us/feed/" rel="self" type="application/rss+xml" />
	<link>http://offermann.us</link>
	<description>More output. Less input.</description>
	<lastBuildDate>Sat, 04 Jul 2009 00:03:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Twitterers Times Two: Multiple Twitter Widgets in a WordPress Sidebar</title>
		<link>http://offermann.us/2009/03/27/twitterers-times-two-multiple-twitter-widgets-in-a-wordpress-sidebar/</link>
		<comments>http://offermann.us/2009/03/27/twitterers-times-two-multiple-twitter-widgets-in-a-wordpress-sidebar/#comments</comments>
		<pubDate>Sat, 28 Mar 2009 00:01:57 +0000</pubDate>
		<dc:creator>Tom Offermann</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[twitter wordpress]]></category>

		<guid isPermaLink="false">http://offermann.us/?p=35</guid>
		<description><![CDATA[How can you include the Twitter updates for more than one person in your Wordpress sidebar? Here's how to tweak the Twitter HTML widget to show multiple users.
]]></description>
			<content:encoded><![CDATA[<p><em>(Or, How I wrote almost 800 words about changing two lines of code&#8230;)</em></p>
<p>My wife and I keep a <a href="http://micheleandtom.com">blog about our recent move to Buenos Aires</a>.  Michele is a non-stop, daily blogging machine, while I write a post, oh about once a month&#8230;which may not be a very impressive body of work, but it certainly beats my track record around here lately!</p>
<p>In addition to my relative lack of posts, what&#8217;s also been missing on our blog has been my Twitter updates in the sidebar.  Why?  Because while Twitter provides a nice, simple <a href="http://twitter.com/widgets">widget</a> that works well for including Twitter updates on the blog, it only works for a single user.</p>
<p>But, what if you have a blog with two writers, and they both want to include their tweets in the sidebar?  Here&#8217;s how I finally solved that problem.</p>
<h3 id="what_goes_wrong_when_you_add_two_twitter_widgets_anyway">What Goes Wrong When You Add Two Twitter Widgets, Anyway?</h3>
<p>I&#8217;m no javascript expert, but Twitter&#8217;s widget code is fairly simple:</p>
<p>First, <a href="http://twitter.com/widgets/html_widget">Twitter generates</a> the following lines of HTML, which you paste into your blog&#8217;s template.  With WordPress, it&#8217;s easiest to put it in a Text Widget in the Sidebar.</p>
<script src="http://gist.github.com/86923.js"></script><noscript><code class="gist"><pre></p>
<ul id="twitter_update_list"></ul>
<p><script type="text/javascript" 
  src="http://twitter.com/javascripts/blogger.js"></script><br />
<script type="text/javascript" 
  src="http://twitter.com/statuses/user_timeline/toffermann.json?callback=twitterCallback2&amp;count=2">
</script><br />
</pre></code></noscript>
<p>The HTML for the second widget looks like this:</p>
<script src="http://gist.github.com/86941.js"></script><noscript><code class="gist"><pre></p>
<ul id="twitter_update_list"></ul>
<p><script type="text/javascript" 
  src="http://twitter.com/javascripts/blogger.js"></script><br />
<script type="text/javascript" 
  src="http://twitter.com/statuses/user_timeline/MichRee.json?callback=twitterCallback2&amp;count=2">
</script><br />
</pre></code></noscript>
<p>Looks familiar, right?  In fact, the only difference is the different Twitter user name in the second script.  It&#8217;s now <code>MichRee.json</code>.</p>
<p>Notice that the <code>&lt;ul&gt;</code> in this widget has the same exact id as the first one: &#8220;<code>twitter_update_list</code>&#8220;.  That&#8217;s where the problem lies, because watch what happens:</p>
<ol>
<li>
<p>In the first Widget Text Box, <code>toffermann.json</code> calls <code>twitterCallback2</code>, which looks for the first unordered list element with an id of &#8220;<code>twitter_update_list</code>&#8221; in the page&#8217;s HTML, where it inserts the list of toffermann&#8217;s tweets.</p>
</li>
<li>
<p>Then, in the second Widget Text Box, <code>MichRee.json</code> calls the same <code>twitterCallback2</code> function, which again searches for the first unordered list with an id of &#8220;<code>twitter_update_list</code>.&#8221;  And, rather than find that list to be empty, this time it finds that toffermann&#8217;s tweets have already been inserted&#8230;so it goes ahead and overwrites them with MichRee&#8217;s tweets.</p>
</li>
</ol>
<p>Final result: One widget displays the wrong updates, while the other widget is blank.</p>
<p>Oops.</p>
<h3 id="my_solution">My Not-So-Easy Two Step Solution</h3>
<ol>
<li><strong>Change the twitterCallback2 Function</strong>
<p>I modified the <code>twitterCallback2</code> function so that it looks for an element ID that includes the Twitter user name, not the hard-coded &#8220;<code>twitter_update_list</code>&#8221; ID.  </p>
<p>After running the <a href="http://twitter.com/javascripts/blogger.js">blogger.js</a> code through <a href="http://www.howtocreate.co.uk/tutorials/jsexamples/JSTidy.html">javascript tidy</a> and changing just the last line of the function, it now looks like this:</p>
<script src="http://gist.github.com/86924.js"></script><noscript><code class="gist"><pre><br />
function twitterCallback2(C)<br />
{<br />
  var A = [];<br />
  for (var D = 0; D < C.length; ++D)<br />
    {<br />
      var E = C[D].user.screen_name;<br />
      var B = C[D].text.replace(/((https?|s?ftp|ssh)://[^"s<>]*[^.,;'">:s<>)]!])/g, function (F)<br />
      {<br />
        return &#8220;<a href="" + F + "">&#8221; + F + &#8220;</a>&#8220;;<br />
      }).replace(/B@([_a-z0-9]+)/ig, function (F)<br />
      {<br />
        return F.charAt(0) + &#8220;<a href="http://www.twitter.com/" + F.substring(1) +<br />
          "">&#8221; + F.substring(1) + &#8220;</a>&#8220;;<br />
      });<br />
      A.push(&#8220;
<li><span>&#8221; + B + &#8220;</span> <a style="font-size:85%" href="http://twitter.com/"<br />
        + E + "/statuses/" + C[D].id + "">&#8221; + relative_time(C[D].created_at) + &#8220;</a></li>
<p>&#8220;);<br />
    }<br />
  document.getElementById(E + &#8220;_twitter_updates&#8221;).innerHTML = A.join(&#8220;&#8221;);<br />
}<br />
</pre></code></noscript>
<p>I saved the modified file as <a href="http://micheleandtom.com/wp-includes/js/twitter-simple.js">wp-includes/js/twitter-simple.js</a>.</p>
</li>
<li><strong>Change the HTML in the Widget Text Boxes</strong>
<p>Include the Twitter user name in the <code>&lt;ul&gt;</code> element ID, and then point to our newly saved <code>twitter.js</code> file.</p>
<p>That means, in Widget Text Box #1, you put:</p>
<script src="http://gist.github.com/86926.js"></script><noscript><code class="gist"><pre></p>
<ul id="MichRee_twitter_updates"></ul>
<p><script type="text/javascript" src="wp-includes/js/twitter-simple.js"></script><br />
<script type="text/javascript"
  src="http://twitter.com/statuses/user_timeline/MichRee.json?callback=twitterCallback2&amp;count=2">
</script><br />
</pre></code></noscript>
<p>And, in Widget Text Box #2:</p>
<script src="http://gist.github.com/86928.js"></script><noscript><code class="gist"><pre>
<ul id="toffermann_twitter_updates"></ul>
<p><script type="text/javascript" 
  src="http://twitter.com/statuses/user_timeline/toffermann.json?callback=twitterCallback2&amp;count=2">
</script><br />
</pre></code></noscript>
</li>
</ol>
<p>And, that&#8217;s that!  You now have updates for two Twitterers on the same page.</p>
<h3 id="that_seems_complicated_aren8217t_there_any_other_solutions">That Seems Complicated.  Aren&#8217;t There Any Other Solutions?</h3>
<p>Why, Yes.  There are a ridiculous number of Twitter-Wordpress solutions out there.  Here is a list of the main contenders I considered that can handle multiple Twitter users&#8230;and the nitpicky reasons why I ultimately rejected them:</p>
<ol>
<li>
<p><a href="http://rick.jinlabs.com/code/twitter/">Twitter for WordPress</a> by Ricardo González.</p>
<p>A strong contender.  But, it&#8217;s not super configurable, so I couldn&#8217;t get the output to look exactly like the output of the Twitter widget.  It can&#8217;t make the timestamp linkable.  And, it doesn&#8217;t always show timestamps for tweets in &#8220;human readable format&#8221;.  I prefer it to say a tweet was posted &#8220;about 4 days ago&#8221;, rather than posted on &#8220;03/22/09&#8221;, but this plugin switches to the dd/mm/yy format if the tweet is more than 24 hours old.</p>
</li>
<li>
<p><a href="http://remysharp.com/2007/05/18/add-twitter-to-your-blog-step-by-step/">twitterjs</a> by Remy Sharp.</p>
<p>Looked promising, but since it&#8217;s not a WordPress plugin, it requires a bit more configuration than I was hoping for.  Plus, it also doesn&#8217;t do &#8220;human readable format&#8221; timestamps for tweets older than 24 hours.  (Though it looks like earlier versions <em>did</em> do it, so I wonder why it changed.)</p>
</li>
<li>
<p><a href="http://xavisys.com/2008/04/wordpress-twitter-widget/">Twitter Widget Pro</a> by Aaron Campbell.</p>
<p>I came very close to using this.  It&#8217;s almost perfect.  But, here&#8217;s where I get really picky&#8230;In addition to the text of the tweet, it also shows its &#8220;source&#8221;.  (As in &#8220;this post was sent by TweetDeck.&#8221;)  I know that twitter.com shows the source as well, but I think it&#8217;s superfluous information, and I don&#8217;t care to show it.</p>
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://offermann.us/2009/03/27/twitterers-times-two-multiple-twitter-widgets-in-a-wordpress-sidebar/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Guide to Household Lingo: Type a Letter to Oprah</title>
		<link>http://offermann.us/2008/08/10/guide-to-household-lingo-type-a-letter-to-oprah/</link>
		<comments>http://offermann.us/2008/08/10/guide-to-household-lingo-type-a-letter-to-oprah/#comments</comments>
		<pubDate>Sun, 10 Aug 2008 22:28:22 +0000</pubDate>
		<dc:creator>Tom Offermann</dc:creator>
				<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://offermann.us/?p=31</guid>
		<description><![CDATA[Starting a big project can be tough. Especially, if we&#8217;re talking about me starting that big project. Since I&#8217;m naturally predisposed to the paralysis that comes from over-thinking, I&#8217;m always on the lookout for stories that inspire me to Just Start. Don&#8217;t worry so much about making a mistake. Don&#8217;t try to figure out optimal [...]]]></description>
			<content:encoded><![CDATA[<p>Starting a big project can be tough.  Especially, if we&#8217;re talking about me starting that big project.</p>
<p>Since I&#8217;m naturally predisposed to the paralysis that comes from over-thinking, I&#8217;m always on the lookout for stories that inspire me to Just Start.  Don&#8217;t worry so much about making a mistake.  Don&#8217;t try to figure out optimal path.  Just Do Something.</p>
<p>The life story of Greg Mortenson, as told in <a href="http://www.amazon.com/Three-Cups-Tea-Mission-Promote/dp/0143038257/">Three Cups of Tea</a>, contains a great example.</p>
<p>Greg is a mountain climber who comes back from his failed summit attempt on K2 determined to build a school for a remote village in Pakistan.  He has no money, next to no possessions, and no idea how to begin.  For his first step, he decides to type a letter to anyone he can think of who might be willing to donate money.  </p>
<p>He doesn&#8217;t use a computer, because he doesn&#8217;t know how.  Working away on an old typewriter, he takes all day to complete his first 6 letters.  All in all, he writes 580 letters.  </p>
<p>He sends the letters to Senators, to rich people, and to various celebrities.  Oprah might help, he thinks.</p>
<p>For all that effort, he gets only a single response (from Tom Brokaw), netting him a total of $100.  A hugely unsuccessful fundraising effort.</p>
<p>You could argue that sending the letters was a complete waste of time, but it got him started.  He took that first step towards his goal.  And now, fifteen years later, his organization, <a href="http://www.ikat.org/">Central Asia Institute</a> has built over 60 schools that provide education to over 25,000 students throughout Pakistan and Afghanistan</p>
<p>Got a big project and you don&#8217;t know where to start?  Type a letter to Oprah.</p>
]]></content:encoded>
			<wfw:commentRss>http://offermann.us/2008/08/10/guide-to-household-lingo-type-a-letter-to-oprah/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Guide to Household Lingo: The Crux Move</title>
		<link>http://offermann.us/2008/08/07/guide-to-household-lingo-the-crux-move/</link>
		<comments>http://offermann.us/2008/08/07/guide-to-household-lingo-the-crux-move/#comments</comments>
		<pubDate>Fri, 08 Aug 2008 04:20:39 +0000</pubDate>
		<dc:creator>Tom Offermann</dc:creator>
				<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://offermann.us/?p=27</guid>
		<description><![CDATA[Another favorite phrase of ours is &#8220;The Crux Move&#8221;. This comes from rock climbing, where, in a given climb, the crux move is the one rated hardest to complete. Master that move and you can reach the top. Otherwise, you fall. I&#8217;m not exactly a climber (among other reasons, I&#8217;m getting increasingly more and more [...]]]></description>
			<content:encoded><![CDATA[<p>Another favorite phrase of ours is &#8220;The Crux Move&#8221;.  This comes from rock climbing, where, in a given climb, the crux move is the one rated hardest to complete.  Master that move and you can reach the top.  Otherwise, you fall.</p>
<p>I&#8217;m not exactly a climber (among other reasons, I&#8217;m getting increasingly more and more afraid of heights as I get older), so how we use it in our house is a little less life-and-death:</p>
<blockquote><p>&#8220;To get the kids to bed on time, we&#8217;ve got to eat dinner early.  That&#8217;s the crux move!&#8221;</p></blockquote>
<p>We&#8217;ve used this phrase for so long and so often, I forget it&#8217;s a bit obscure.  But, recently reading about a phrase with a similar meaning made me think about it again.</p>
<p>The new phrase came from a <a href="http://www.newyorker.com/reporting/2008/03/24/080324fa_fact_mcgrath?currentPage=all"> profile of Lenny Dykstra</a> in the New Yorker:</p>
<blockquote><p>&#8220;The one-one count is another of Dykstra’s baseball metaphors for life, meant to illustrate that some moments, and the choices they bring, are more fateful than others (i.e., the next pitch makes all the difference), or, in this case, that circumstances set in motion during the early stages of development are difficult to overcome later on. If a batter falls behind, one ball and two strikes, he’s in a hole from which, the statistics augur, he will not recover, even if he is Barry Bonds; and if he gets ahead, to two balls and one strike, he wrests control from the pitcher and takes charge of his own destiny.&#8221;</p></blockquote>
<p>Have we been using our beloved &#8220;Crux Move&#8221; for too long?  Perhaps it&#8217;s time to phase it out.  Should &#8220;One-One Count&#8221; be the one to replace it?  Can my wife stand to hear me quote the wisdom of Lenny Dykstra on a regular basis? Time will tell&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://offermann.us/2008/08/07/guide-to-household-lingo-the-crux-move/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The Big Mo</title>
		<link>http://offermann.us/2008/08/07/the-big-mo/</link>
		<comments>http://offermann.us/2008/08/07/the-big-mo/#comments</comments>
		<pubDate>Fri, 08 Aug 2008 01:40:46 +0000</pubDate>
		<dc:creator>Tom Offermann</dc:creator>
				<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://offermann.us/?p=21</guid>
		<description><![CDATA[Losing momentum is a dangerous thing for me. Once I set something aside for more than a few days, there&#8217;s a good chance I&#8217;ll never get back to it. Which means that my short-lived blog is already at a critical stage. My last post promised updates &#8220;in the next few days&#8221;, and now here it [...]]]></description>
			<content:encoded><![CDATA[<p>Losing momentum is a dangerous thing for me.  Once I set something aside for more than a few days, there&#8217;s a good chance I&#8217;ll never get back to it.  </p>
<p>Which means that my short-lived blog is already at a critical stage.  My <a href="http://offermann.us/2008/06/08/guide-to-household-lingo-squash-in-the-fridge/">last post</a> promised updates &#8220;in the next few days&#8221;, and now here it is, almost two months later, and I haven&#8217;t posted a thing.</p>
<p>Clearly, I&#8217;ve lost my blogging momentum.</p>
<p>Let&#8217;s try to pick up where I last left off and pretend like none of this happened.  And, I&#8217;ll try not to lose the &#8220;Big Mo&#8221; again.</p>
]]></content:encoded>
			<wfw:commentRss>http://offermann.us/2008/08/07/the-big-mo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Guide to Household Lingo: Squash in the Fridge</title>
		<link>http://offermann.us/2008/06/08/guide-to-household-lingo-squash-in-the-fridge/</link>
		<comments>http://offermann.us/2008/06/08/guide-to-household-lingo-squash-in-the-fridge/#comments</comments>
		<pubDate>Sun, 08 Jun 2008 19:21:27 +0000</pubDate>
		<dc:creator>Tom Offermann</dc:creator>
				<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://offermann.us/?p=20</guid>
		<description><![CDATA[Sometimes it feels like we speak our own language at our house. But, I&#8217;m guessing that that&#8217;s not unusual. Don&#8217;t inside jokes and obscure references make up the bulk of most conversations? Over time, we find that some phrases fall by the wayside, but others, often the unlikeliest ones, become conversation shorthand that we use [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes it feels like we speak our own language at our house.  But, I&#8217;m guessing that that&#8217;s not unusual.  Don&#8217;t inside jokes and obscure references make up the bulk of most conversations?</p>
<p>Over time, we find that some phrases fall by the wayside, but others, often the unlikeliest ones, become conversation shorthand that we use again and again.</p>
<p>Consider the next series of blog posts to be a phrase book, useful for decoding the strange expressions you might hear us say.  Today, we&#8217;ll start with a golden oldie, then in the following days, move onto more recent additions.</p>
<h3 id="squash_in_the_fridge">Squash in the Fridge</h3>
<p>Ten years ago, my brother-in-law overheard me call out:</p>
<blockquote>
<p>&#8220;Honey!  The butternut squash&#8212;do you store it on the counter or do you keep it in the fridge?&#8221;</p>
</blockquote>
<p>Oh, no!  Crisis!</p>
<p>At the time, he was in a relationship that was going through a period of high drama.  What kind of a future did he and his girlfriend have?  Should they even stay together?  (Ultimately, they didn&#8217;t.)</p>
<p>The contrast between their relationship and ours was too much.  Obviously, my brother-in-law concluded, my wife and I were leading a ridiculously pampered life, since the most pressing issues we had to deal with in our relationship involved the proper storage of fruits and vegetables.</p>
<p>So, now anytime my wife and I find ourselves nattering endlessly about some everyday minutia, and we need a reminder of just how inconsequential our argument is, one of us will stop, look at the other and say: </p>
<blockquote>
<p>&#8220;It&#8217;s like squash in the fridge.&#8221;</p>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://offermann.us/2008/06/08/guide-to-household-lingo-squash-in-the-fridge/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Last Google IO Post: The Sticky Stuff</title>
		<link>http://offermann.us/2008/06/02/last-google-io-post-the-sticky-stuff/</link>
		<comments>http://offermann.us/2008/06/02/last-google-io-post-the-sticky-stuff/#comments</comments>
		<pubDate>Tue, 03 Jun 2008 04:58:35 +0000</pubDate>
		<dc:creator>Tom Offermann</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://offermann.us/?p=19</guid>
		<description><![CDATA[&#8220;I&#8217;m just trying to figure out this audience&#8230;it&#8217;s all dudes&#8230;Google is run by dudes!&#8221; &#8212;Bret McKenzie, from Flight of the Conchords, as he surveyed the crowd during their performance at Google IO last week. Google Put on Quite a Show Last Week In my last posts that focused on the developer sessions and keynotes, I [...]]]></description>
			<content:encoded><![CDATA[<p><em>&#8220;I&#8217;m just trying to figure out this audience&#8230;it&#8217;s all dudes&#8230;Google is run by dudes!&#8221;</em><br /> &#8212;Bret McKenzie, from Flight of the Conchords, as he surveyed the crowd during their performance at Google IO last week.</p>
<h3>Google Put on Quite a Show Last Week</h3>
<p>In my last posts that focused on the <a href="http://offermann.us/2008/05/29/day-one-at-google-io/">developer sessions</a> and <a href="http://offermann.us/2008/05/30/marissa-mayer-at-google-io/">keynotes</a>, I didn&#8217;t really capture the overall feel of <a href="http://code.google.com/events/io/">Google IO</a>, leaving out a few key details&#8230;</p>
<h3>Like the Food</h3>
<p>Google is famous for pampering its employees with their gourmet fare, and they went all out to pamper their conference goers as well.  Full breakfasts, numerous lunch choices (I went with the grilled skirt steak myself), and an endless sea of snacks.  There was a wall of candy bins, freezers full of Haagen Dazs Ice Cream bars, and constantly replenished sodas.</p>
<p>And, strategically placed throughout the Moscone Center were Googly colored bean bags upon which you could plop down and enjoy the bounty.</p>
<h3>The Evening Party</h3>
<p>Where there was even more food.  And everflowing beer and wine&#8230;and molten chocolate.  (Yes, there were fountains of molten chocolate, in which you could dip your marshmallows and cakes on a stick.)  But, there was more than food.  Everywhere you looked: Dozens of video games.  Foosball tables.  Billiards.  Air Hockey.  Big screen Wiis.</p>
<p>As I overheard one conference goer describe the scene:</p>
<pre>"It's like a sixth grader's wet dream."</pre>
<h3>Did I Mention the Band?</h3>
<p>Now, understand that I&#8217;m old.  And, I don&#8217;t have HBO.  So, I&#8217;d never heard of <a href="http://www.conchords.co.nz/">Flight of the Conchords</a>.  (When I looked them up on YouTube, I was shocked that each of their songs had over 1 million views.  What do I know?)  It turns out that this &#8220;folk-comedy duo&#8221; from New Zealand is kind of a thinking man&#8217;s Spinal Tap, with a gift for deadpan, hipster patter.</p>
<p>Because, it wasn&#8217;t so much their songs that had me entertained, as it was their rambling stories that they interwove into the music.  They told tales of traveling in time, and being locked in David Bowie&#8217;s bathroom with not one, but two Tina Turners (one from the future, naturally), and fathering tiny, imaginary children.</p>
<p>At least that&#8217;s what I thought as I walked back to my hotel on Wednesday night: funny shtick, funny stories, amazing delivery.</p>
<p>But, I was wrong.  Their music made more of an impact than I first gave it credit for, because it is now 5 days later, and I still have their closing number going through my head.  You know, the one where the entire audience rose from their Googly bean bags, waved their hands in the air, and sang along:</p>
<pre>
  Brown paper, white paper
  Stick it together with tape
  The tape of love
  The sticky stuff.
</pre>
<p><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/fycGFGSeKpc&#038;hl=en"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/fycGFGSeKpc&#038;hl=en" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://offermann.us/2008/06/02/last-google-io-post-the-sticky-stuff/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Marissa Mayer&#8217;s Day 2 Speech at Google IO</title>
		<link>http://offermann.us/2008/05/30/marissa-mayer-at-google-io/</link>
		<comments>http://offermann.us/2008/05/30/marissa-mayer-at-google-io/#comments</comments>
		<pubDate>Sat, 31 May 2008 05:46:43 +0000</pubDate>
		<dc:creator>Tom Offermann</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://offermann.us/?p=18</guid>
		<description><![CDATA[Uh oh. Marissa Mayer kicks off her speech by talking about artists and fashion designers creating custom background images to use on iGoogle home pages. This is what&#8217;s exciting at Google right now? Minutes go by, and still more fluffy iGoogle talk. Now, I&#8217;m really worried&#8230;she&#8217;s going to crash and burn. I mean, she&#8217;s speaking [...]]]></description>
			<content:encoded><![CDATA[<p>Uh oh.</p>
<p>Marissa Mayer kicks off her speech by talking about artists and fashion designers creating custom background images to use on iGoogle home pages.  This is what&#8217;s exciting at Google right now?</p>
<p>Minutes go by, and still more fluffy iGoogle talk.  Now, I&#8217;m really worried&#8230;she&#8217;s going to crash and burn.  I mean, she&#8217;s speaking at a conference for developers&#8230;and she&#8217;s talking about wallpaper?</p>
<p>Thankfully, once she really got going, her speech turned out to be quite entertaining and was filled with funny stories about the early days of Google.</p>
<p>Some tidbits:</p>
<ul>
<li>
<p>She once asked Sergey Brin to explain the spare design of the original Google home page:</p>
<pre>&#8220;We didn&#8217;t have a webmaster&#8230;and I don&#8217;t do HTML.&#8221;
</pre>
</li>
<li>
<p>Early user testers would just stare at the Google home page&#8230;and not type anything into the search box.  </p>
<p>Why?  </p>
<p>They were waiting for the rest of the page to load.</p>
<p>To solve this problem, Google had to add a footer, so people knew the home page was done loading.</p>
<pre>&#8220;Our copyright notice isn&#8217;t legally required.  It&#8217;s punctuation.&#8221;
</pre>
</li>
<li>
<p>Every search query on Google hits between 700 to 1000 servers before serving the response.  Think about that the next time your search results return in 0.09 seconds.</p>
</li>
<li>
<p>&#8220;Design is becoming more of a science than an art.&#8221;</p>
<p>They do tons of A/B Testing at Google, testing every tweak to the site on a small percentage of their users and then watching to see how it impacts their &#8220;Happiness Metrics&#8221;.  Which means that they don&#8217;t have to guess which design or feature is better.  They have numbers, hard evidence that one is better than another.</p>
<p>Two examples:</p>
<ul>
<li>Less white space around their logo made their users more satisfied.</li>
<li>Displaying more search results per query caused happiness to plummet, because adding even the tiniest fraction of a second to the page response time resulted in decreasing user satisfaction.</li>
</ul>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://offermann.us/2008/05/30/marissa-mayer-at-google-io/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Day One at Google IO</title>
		<link>http://offermann.us/2008/05/29/day-one-at-google-io/</link>
		<comments>http://offermann.us/2008/05/29/day-one-at-google-io/#comments</comments>
		<pubDate>Thu, 29 May 2008 08:34:39 +0000</pubDate>
		<dc:creator>Tom Offermann</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[appengine]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://offermann.us/?p=17</guid>
		<description><![CDATA[I&#8217;m at the Google IO Conference in San Francisco. It&#8217;s late at night&#8230;I&#8217;m still decompressing and trying to make sense of my notes from the day&#8217;s sessions. I&#8217;ve put myself on a self-imposed &#8220;App Engine Only&#8221; track, so I haven&#8217;t really followed the news and announcements regarding Android, or OpenSocial, or Google Gears, or any [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m at the <a href="http://code.google.com/events/io/">Google IO Conference</a> in San Francisco.  It&#8217;s late at night&#8230;I&#8217;m still decompressing and trying to make sense of my notes from the day&#8217;s sessions.</p>
<p>I&#8217;ve put myself on a self-imposed &#8220;App Engine Only&#8221; track, so I haven&#8217;t really followed the news and announcements regarding Android, or OpenSocial, or Google Gears, or any other Google initiative.  </p>
<p>Though they did show a way cool Android mobile phone demo in the Keynote.  The phone had a built-in compass, so you could run the Google Maps application and look at the Street View, and then as you moved the phone, the Street View would sync to the new compass direction.  In other words, as you moved the phone from North to South, the Street View photos would also pan from the North view to the South view.  Spontaneous cheering from the crowd.</p>
<h3 id="app_engine_talks">App Engine Talks</h3>
<p>In any event, here are my takeaways from today:</p>
<ul>
<li>
<p>Use Django.  Don&#8217;t use the one that&#8217;s bundled with App Engine (v. 0.96).  No, check out the latest development version of Django from subversion (currently 0.97).  What&#8217;s interesting is that even though Google App Engine ships with the webapp framework and with Django 0.96, Guido van Rossum chose to devote his talk to how to install and use Django 0.97 on Google App Engine.  I was curious what that meant for webapp, so I asked if there was ever a reason to use webapp instead of Django.  Guido&#8217;s answer was that webapp was simple and enabled you to get started very quickly.  But, Django was more powerful.</p>
</li>
<li>
<p>If you use the Datastore correctly, scaling comes for free.  But, it takes a lot of work to use the datastore correctly.  Further complicating the issue is that nobody knows exactly what &#8220;correctly&#8221; means yet.</p>
</li>
<li>
<p>Pay special attention to Datastore writes.  &#8220;Reads are cheap!  Writes are expensive!&#8221;  Every write is a serialized transaction that hits the disk.  Rule of thumb says you can&#8217;t do more than ~100 seeks/sec, so that&#8217;s the upper limit for write speed.</p>
</li>
<li>
<p>For high-contention write situations (like a counter), don&#8217;t write to a single, global counter class.  Instead, use &#8220;sharded writes&#8221; where you write to several entities, and then sum the totals from all the shards to get the total count.</p>
</li>
<li>
<p>Entity Groups are for transactions.  I did not understand the point of parent-child hierarchies for entities before today, but now I see that their only purpose is to group entities that need to be changed together as a part of a transaction.</p>
</li>
<li>
<p>The Datastore will <strong>not</strong> help you maintain data integrity.  It&#8217;s entirely up to you, especially when you are updating or deleting entities with ReferenceProperties.  Seeing the code examples today that showed how to handle deletes properly makes me appreciate how nice it is to have a relational DB handle this automatically.</p>
</li>
<li>
<p>Don&#8217;t use count().  <strong>Ever</strong>.  This was stressed in several presentations.  Not only can it <a href="http://code.google.com/appengine/docs/datastore/gqlqueryclass.html#GqlQuery_count">not count past 1000</a>, but it also requires a scan of every entity, thereby using way too much processing power.</p>
</li>
<li>
<p>You can&#8217;t use JOINs in queries, but you can utilize the foreign-key-like ReferenceProperty to associate entities and therefore, do JOIN-like queries on them.  In Rafe Kaplan&#8217;s talk about &#8220;Working with Google App Engine Models&#8221;, he walked through one way to model one-to-many and many-to-many relationships.  I found this particularly interesting, in that it demonstrates how to have a relatively normalized data model, directly contradicting the emerging idea that the best way to take advantage of the Datastore is <a href="http://highscalability.com/how-i-learned-stop-worrying-and-love-using-lot-disk-space-scale">aggressive de-normalization</a>.</p>
</li>
<li>
<p>The index.yaml file defines the composite keys needed for complex queries.  All queries rely on the Indexes, which are separate BigTable tables.  If a property value isn&#8217;t indexed, it can&#8217;t be found by a query.  Now, that&#8217;s not a problem for querying by kind or single property values, since indexes are created for these automatically, but it is relevant for complex queries, since composite keys are not created automatically.  (The dev server automatically updates the index.yaml file as complex queries are run in the dev environment, so as long as you test every query on dev, you&#8217;ll be fine.)</p>
</li>
</ul>
<p>Several themes came up over and over in the Q&amp;As that followed the talks:</p>
<ul>
<li>
<p><strong>Maintaining Data Integrity, Especially over Time</strong>.  How do I migrate data models?  How do I delete columns, or rename columns?  How do I rename classes?  How can I make changes and not break data integrity?  Nobody&#8217;s figured out good answers to these questions yet.</p>
</li>
<li>
<p><strong>Bulk Data Operations</strong>.  How can I import and export large data sets?  How can I bulk delete?  The App Engine team stressed that they were well aware of this limitation.</p>
</li>
<li>
<p><strong>Full-Text Search</strong>.  How can I do full-text search over my data?  Shockingly, developers uniformly expect Google to be really good at full-text search&#8230;imagine that!  Sadly, it&#8217;s not there yet, though Google engineers mentioned that there&#8217;s &#8220;currently a hack in place that kind of works&#8221;, and that they would provide this feature sometime in the future.</p>
</li>
</ul>
<p>In his presentation on how the Datastore works under the hood, Ryan Barrett offhandedly mentioned the three big priorities for the Google App Engine Team right now:</p>
<ol>
<li>Data Import/Export</li>
<li>Additional languages</li>
<li>Billing</li>
</ol>
<p>All in all, the Google App Engine talks were fascinating.  Using Datastore is so new, and it&#8217;s such a departure from using a relational DB, that it&#8217;s exciting to see everyone try to figure out how to best utilize it.  Though, one thing I was struck by was how tentative some of the suggestions were from the Google engineers.    I had expected that since they have several years of experience building applications on top of BigTable, that they would have created more definitive best practices for how to handle common data models and for maintaining data integrity.  Perhaps it&#8217;s so new that even Google is still figuring out how best to work with it.</p>
]]></content:encoded>
			<wfw:commentRss>http://offermann.us/2008/05/29/day-one-at-google-io/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>First BarCamp For Me</title>
		<link>http://offermann.us/2008/05/05/first-barcamp-for-me/</link>
		<comments>http://offermann.us/2008/05/05/first-barcamp-for-me/#comments</comments>
		<pubDate>Mon, 05 May 2008 22:32:22 +0000</pubDate>
		<dc:creator>Tom Offermann</dc:creator>
				<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://offermann.us/?p=15</guid>
		<description><![CDATA[Portland&#8217;s second ever BarCamp (a free-form &#8220;unconference&#8221;) was held this weekend, and since there were no soccer or Little League games for me on Sunday, I was able to catch one day&#8217;s sessions. Not knowing what to expect when I arrived, I quickly found an enthusiastic crowd, plentiful food (bagels stacked high and all the [...]]]></description>
			<content:encoded><![CDATA[<p>Portland&#8217;s second ever <a href="http://barcamp.org/BarCampPortland">BarCamp</a> (<a href="http://en.wikipedia.org/wiki/BarCamp">a free-form &#8220;unconference&#8221;</a>) was held this weekend, and since there were no soccer or Little League games for me on Sunday, I was able to catch one day&#8217;s sessions.</p>
<p>Not knowing what to expect when I arrived, I quickly found an enthusiastic crowd, plentiful food (bagels stacked high and all the Bubble Tea you could drink), and lots of interesting sessions, with topics ranging from WordPress to CrossFit to Bikes to Patents to Predicting the Stock Market.</p>
<h3>You are Your Twitter Name</h3>
<p>As you register, you&#8217;re handed a badge so you can write your name and other key information.  But, you don&#8217;t identify yourself by your email address, or your blog, or your domain name.  Instead, at BarCamp Portland, your identity <strong>is</strong> your Twitter identity.  </p>
<p>As I looked around at other people&#8217;s badges, I noticed that nearly <strong>everyone</strong> had a <a href="http://twitter.com/toffermann">Twitter name</a>.</p>
<p>I was surprised at how ubiquitous Twitter was.  &#8220;What&#8217;s wrong with the alternatives?&#8221;, I wondered.  Here&#8217;s my stab at some answers:</p>
<ul>
<li><strong>Email</strong>.  Too much spam.  People suffer from email overload.  Plus, there&#8217;s no way to learn more about someone if you have only their email address.</li>
<li><strong>Blog</strong>.  Not everyone has a blog.  It&#8217;s much easier to start twittering than it is to set up and maintain a blog.</li>
</ul>
<p>Whatever the reason, Portland BarCampers have clearly chosen Twitter their default online profile.</p>
<h3>WordPress as CMS</h3>
<p>I sat in on several WordPress-oriented sessions, and &#8220;Using WordPress as a CMS&#8221; was my favorite.  <a href="http://twitter.com/notbenh">Ben Hengst</a> from Powell&#8217;s Books talked about they were using WordPress on <a href="http://powells.com/">powells.com</a>.  </p>
<p>The Powell&#8217;s Web site is made up of many different systems (some written in perl, some in PHP), and WordPress currently only powers the <a href="http://www.powells.com/blog/">PowellsBooks.Blog</a> section of the site on the front-end.  But, as the developers and Marketing folk began to use WordPress more and more, they found that it offered a simple interface for Marketing folk to input reusable content, and that it&#8217;s database structure could handle the different types of content they required.  Ben said that using a combination of tags and categories gave them all the flexibility they needed. </p>
<p>So, now, they are inputting content with the WordPress Admin interface on the back-end, but then pulling that content from the WordPress database with the perl and PHP code that runs the rest of the site.  In other words, much of the content that is entered in WordPress is never displayed by WordPress.</p>
<h3>Random Observations</h3>
<p>Sometimes it&#8217;s the little things that you see or hear about that make the event worthwhile.  </p>
<ul>
<li>I heard the story of writing an innocent blog post about <a href="http://www.mywhimislaw.com/?p=1212">how you are unable to burp on demand</a>&#8230;and watching a whole community of non-burpers spring up around it.</li>
<li><a href="http://reidab.com/">Reid Beels</a> was giving an overview of how to write a WordPress plugin&#8230;and then offhandedly demoed a really cool <a href="http://swashbuckled.com/">javascript photo display</a> (hover over one photo and see how the rest of the photos evenly resize).</li>
<li>I spotted someone wearing not only a <a href="http://www.utilikilts.com/">Utilikilt</a>, but <a href="http://www.vibramfivefingers.com/">Vibram Five Fingers</a> shoes as well.  A somewhat radical look&#8230;but he totally pulled it off.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://offermann.us/2008/05/05/first-barcamp-for-me/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Can&#8217;t Avoid Being on the Web</title>
		<link>http://offermann.us/2008/05/02/cant-avoid-being-on-the-web/</link>
		<comments>http://offermann.us/2008/05/02/cant-avoid-being-on-the-web/#comments</comments>
		<pubDate>Sat, 03 May 2008 04:46:16 +0000</pubDate>
		<dc:creator>Tom Offermann</dc:creator>
				<category><![CDATA[Personal]]></category>

		<guid isPermaLink="false">http://offermann.us/?p=9</guid>
		<description><![CDATA[(Or, An excuse to compile a bunch of links about myself for Mom&#8230;) These days, you don&#8217;t even have to make an effort to be on the Internet. Even without starting a blog, you&#8217;ll find that your name, or your photo, or even a video of you, will somehow make its way onto the Web. [...]]]></description>
			<content:encoded><![CDATA[<p><em>(Or, An excuse to compile a bunch of links about myself for Mom&#8230;)</em></p>
<p>These days, you don&#8217;t even have to make an effort to be on the Internet.  Even without starting a blog, you&#8217;ll find that your name, or your photo, or even a video of you, will somehow make its way onto the Web.</p>
<ul>
<li>
<p>All you have to do is work out at a gym.</p>
<p>My gym is called <a href="http://www.crossfithel.com/">Crossfit HEL</a>.  (Add an &#8216;L&#8217; for an even more appropriate name&#8230;)  Every time I complete a &#8220;Workout of the Day&#8221; (WOD), <a href="http://coachk.typepad.com/workout_of_the_day_blog/2007/10/track-day.html">my</a> <a href="http://coachk.typepad.com/workout_of_the_day_blog/2007/10/coming-home.html">time</a> <a href="http://coachk.typepad.com/workout_of_the_day_blog/2007/11/trying-somethin.html">or</a> <a href="http://coachk.typepad.com/workout_of_the_day_blog/2008/01/the-front-squat.html">score</a> <a href="http://coachk.typepad.com/workout_of_the_day_blog/2008/02/fgb.html">is</a> <a href="http://coachk.typepad.com/workout_of_the_day_blog/2008/02/september-11th.html">posted</a> on the <a href="http://coachk.typepad.com/workout_of_the_day_blog/">CrossFit HEL blog</a>.  Sometimes, my <a href="http://coachk.typepad.com/workout_of_the_day_blog/2008/01/chipper.html">photo</a> is even <a href="http://coachk.typepad.com/workout_of_the_day_blog/2007/10/o-course.html">posted</a>.</p>
</li>
<li>
<p>Or, you can just take an <a href="http://thecrossfitrevolution.blogspot.com/2008/03/olympic-class-march-16th-2008.html">Olympic Weightlifting class</a>.  (I&#8217;m in the back row.)</p>
<p><embed src="http://www.blogger.com/img/videoplayer.swf?videoUrl=http%3A%2F%2Fvp.video.google.com%2Fvideodownload%3Fversion%3D0%26secureurl%3DqgAAADbdx0ctBZ6r0jjgHMEoxaZ3WDBLdEkOP-ojGjQYVTp4WMMa3OYUy8Vb4MyopT1iNCM6Ra2YbN7yCU9uialKQaQciyGU_qtPWeikl9B5lXtoANCk94KfxGGJtHRxhgvRDxMHLj523PDKQ842nh9e1SijCAp-fi6ObCpqY0tt3IY0-zvT3sO9G9PwZApBpIRuEdCocpzaXnY9CGSuZ9-bdYRZNB9Gcgi_4ktB4fz1O_qU%26sigh%3DzeYeTlVquzK9J7_Rx9zG7DegGAQ%26begin%3D0%26len%3D86400000%26docid%3D0&amp;nogvlm=1&amp;thumbnailUrl=http%3A%2F%2Fvideo.google.com%2FThumbnailServer2%3Fapp%3Dblogger%26contentid%3D83cfb3024bda2558%26offsetms%3D5000%26itag%3Dw320%26sigh%3Drtu_6jIzv1PGkftPrY8xeeH71Zc&amp;messagesUrl=video.google.com%2FFlashUiStrings.xlb%3Fframe%3Dflashstrings%26hl%3Den" type="application/x-shockwave-flash" height="266" width="320"><br />
</embed></p>
</li>
<li>
<p>Or, you can take a <a href="http://www.portlandpreserve.com/">class</a> on <a href="http://cookingupastory.com/index.php/2007/07/19/preserving-food-and-friendship/">making strawberry jam</a>.  (I&#8217;m the only guy in the video.)</p>
<p><embed src="http://services.brightcove.com/services/viewer/federated_f8/717175604" bgcolor="#000000" flashVars="videoId=1119252139&#038;playerId=717175604&#038;viewerSecureGatewayURL=https://services.brightcove.com/services/amfgateway&#038;servicesURL=http://services.brightcove.com/services&#038;cdnURL=http://admin.brightcove.com&#038;domain=embed&#038;autoStart=false&#038;" base="http://admin.brightcove.com" name="flashObj" width="320" height="256" seamlesstabbing="false" type="application/x-shockwave-flash" swLiveConnect="true" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"></embed></p>
</li>
</ul>
<p>I guess nowadays, there are no offline activities.  All offline activities inevitably wind up online.</p>
]]></content:encoded>
			<wfw:commentRss>http://offermann.us/2008/05/02/cant-avoid-being-on-the-web/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
