<?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>Push cx &#187; Code</title>
	<atom:link href="http://push.cx/category/code/feed" rel="self" type="application/rss+xml" />
	<link>http://push.cx</link>
	<description>A traveling geek&#039;s blog on development, games, and the web</description>
	<lastBuildDate>Thu, 19 Apr 2012 20:39:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Recreating My Firefox Profile</title>
		<link>http://push.cx/2011/recreating-my-firefox-profile</link>
		<comments>http://push.cx/2011/recreating-my-firefox-profile#comments</comments>
		<pubDate>Sat, 25 Jun 2011 03:54:22 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[customization]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[nerd pride]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1798</guid>
		<description><![CDATA[With the release of Firefox 5 a few days ago, I thought it was time to recreate my Firefox profile. You may not know what it is because you only have one: it&#8217;s the set of your add-ons, bookmarks, history, and every other kind of customization you can do to Firefox. As a web developer, [...]]]></description>
			<content:encoded><![CDATA[<p>
  With the release of <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2Jsb2cubW96aWxsYS5jb20vYmxvZy8yMDExLzA2LzIxL21vemlsbGEtZGVsaXZlcnMtbmV3LXZlcnNpb24tb2YtZmlyZWZveC1maXJzdC13ZWItYnJvd3Nlci10by1zdXBwb3J0LWRvLW5vdC10cmFjay1vbi1tdWx0aXBsZS1wbGF0Zm9ybXMv">Firefox 5</a> a few days ago, I thought it was time to recreate my Firefox profile. You may not know what it is because you only have one: it&#8217;s the set of your add-ons, bookmarks, history, and every other kind of customization you can do to Firefox.
</p>

<p>
  As a web developer, I have a half-dozen for testing reasons, but one that I use for all of my personal browsing and most of my work. Very infrequently, I&#8217;ve noticed that it sometimes would have errors on web pages that other Firefox profiles didn&#8217;t. After some thinking, I realized that I&#8217;ve been copying the same Firefox profile nearly ten years, copying it between computers as I upgrade. And all the while I&#8217;ve been tinkering with it, poking around in its config files, testing extensions, changing options in about:config.
</p>

<p>
  I wanted a fairly mindless activity today, so I recreated my profile from scratch, re-installing all my extensions and configuring everything just the way I like it. It took a few hours, and my notes ended up surprisingly long.
</p>

<p>
  The few times I&#8217;ve thought about switching to Chrome I&#8217;ve looked for one or two of these add-ons and seen that there&#8217;s no equivalent. Now that I have these notes I can check comprehensively the next time I get the urge.
</p>

<p>
  The notes will mostly be of interest to web developers. My browser is pretty heavily customized with tools, privacy protections, and productivity tweaks (mostly to make it feel like vim and allow me to pull things offline easily). It&#8217;s an intimidating list to look at, but it&#8217;s ten years of small changes every few weeks all at once.
</p>


<h3>Add-Ons</h3>
<ul>
<li>AdBlock Plus http://adblockplus.org/en/

<ul>
<li>add EasyList (button in tab on startup)</li>
<li>&#8216;Options&#8217; menu, uncheck &#8216;Show tabs on Flash and Java&#8217;</li>
</ul>
</li>
<li>Better Privacy

<ul>
<li>select any LSOs you want to keep</li>
</ul>
</li>
<li>Cookie Monster

<ul>
<li>uncheck &#8220;Automatically Reload&#8230;&#8221;</li>
</ul>
</li>
<li>Download Statusbar

<ul>
<li>General

<ul>
<li>check &#8216;Download speed&#8217;</li>
<li>uncheck &#8216;Keep a download history</li>
<li>check &#8216;Clear finished downloads when the browser closes&#8217;</li>
<li>&#8216;Automatically clear these filetypes&#8217;: *</li>
<li>after 90 seconds</li>
</ul>
</li>
<li>Appearance &#8211; choose &#8216;Custom Style&#8217;

<ul>
<li>File Name Size: 9</li>
<li>Height: 13</li>
<li>check &#8216;Main Downloads Button&#8217;</li>
<li>check &#8216;Clear Finished Button&#8217;</li>
<li>check &#8216;Enable Speed Colors&#8217;</li>
</ul>
</li>
</ul>
</li>
<li>FacebookBlocker</li>
<li>Flashblock

<ul>
<li>check &#8216;Block Silverlight as well&#8217;</li>
<li>add any whitelist sites</li>
</ul>
</li>
<li>Greasemonkey</li>
<li>LeechBlock

<ul>
<li>block tvtropes.com</li>
<li>General &#8211; check all</li>
</ul>
</li>
<li>Pentadactyl
    <p>~/.pentadactylrc</p>
    <code lang=""><pre>
"1.0b4.3 (created: 2011/01/05 17:55:12)

loadplugins '\.(js|penta)$'
set guioptions=BrsC
set runtimepath=/home/harkins/.pentadactyl
set urlseparator=,,s

" vim: set ft=pentadactyl:
</pre></code>
</li>
<li>NoSquint

<ul>
<li>Zooming tab, uncheck &#8216;Show current zoom levels&#8217;</li>
<li>Set &#8216;Default full page zoom level&#8217; to 100%</li>
<li>Exceptions tab, add <em>.github.com, </em>.tumblr.com, <em>.blogspot.com, </em>.posterous.com</li>
</ul>
</li>
<li>Pixlr Grabber

<ul>
<li>uncheck &#8216;To edit images&#8217; and &#8216;To edit backgrounds&#8217;</li>
<li>select &#8216;Always save to desktop&#8217;</li>
</ul>
</li>
<li>Readability https://www.readability.com/addons</li>
<li>RefControl

<ul>
<li>click &#8216;Edit&#8217; button, choose &#8216;Block&#8217; and check &#8217;3rd Party requests only&#8217;</li>
<li>outside of settings, right click button at bottom of window, remove icon</li>
</ul>
</li>
<li>Sauce Launcher https://addons.mozilla.org/en-us/firefox/addon/sauce-launcher/</li>
<li>ScrapBook

<ul>
<li>Show up to: 10</li>
</ul>
</li>
<li>SQLite Manager

<ul>
<li>select &#8216;in a new tab&#8217;</li>
<li>uncheck &#8216;Always confirm&#8217;</li>
<li>uncheck everything in Prompts tab</li>
</ul>
</li>
<li>Tamper Data</li>
<li>Tree Style Tab

<ul>
<li>Appearance

<ul>
<li>Skin &#8216;Sidebar&#8217;</li>
<li>Tree Twisties: choose &#8216;None&#8217;</li>
</ul>
</li>
<li>Menu

<ul>
<li>uncheck all but &#8216;Reload this Tree&#8217; and &#8216;Close this Tree&#8217;</li>
</ul>
</li>
<li>New Tabs

<ul>
<li>uncheck &#8216;Always ask&#8217;</li>
<li>select &#8216;Open in new tabs&#8217;</li>
</ul>
</li>
<li>Tree

<ul>
<li>uncheck &#8216;When a tab gets focus&#8217;</li>
<li>check &#8216;Double-click on a tab&#8217;</li>
</ul>
</li>
<li>Advanced

<ul>
<li>uncheck &#8216;Enable Animation Effects&#8217;</li>
<li>uncheck &#8216;Show tree contents&#8217;</li>
</ul>
</li>
</ul>
</li>
<li>UnPlug

<ul>
<li>Integration &#8211; uncheck all but tools menu</li>
<li>Downloads &#8211; &#8216;Preferred download method&#8217;: Save as</li>
</ul>
</li>
<li>User Agent Switcher</li>
<li>Web Developer

<ul>
<li>General

<ul>
<li>Check to hide the context menu, confirmation, and informational</li>
</ul>
</li>
<li>Validation

<ul>
<li>select CSS 3</li>
</ul>
</li>
</ul>
</li>
</ul>



<h3>Incompatible</h3>
  <p>These aren&#8217;t yet compatible with Firefox 5, so they didn&#8217;t get into my notes.</p>

  <ul>
    <li><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2NvZGUuZ29vZ2xlLmNvbS9zcGVlZC9wYWdlLXNwZWVkL2Rvd25sb2FkLmh0bWw=">Page Speed</a></li>
    <li><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9hZGRvbnMubW96aWxsYS5vcmcvZW4tdXMvZmlyZWZveC9hZGRvbi9yZXN1cnJlY3QtcGFnZXMv">Resurrect Pages</a></li>
    <li><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9hZGRvbnMubW96aWxsYS5vcmcvZW4tdXMvZmlyZWZveC9hZGRvbi95c2xvdy8=">YSlow</a></li>
  </ul>

<h3>GreaseMonkey Scripts</h3>
  <p>Sorry for the lack of titles, but this was annoying enough to compile already.</p>
  <p>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvNTEyODE=">51281</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvNjI3MDY=">62706</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvNzcwNQ==">7705</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMjM1NTU=">23555</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvNTM1NDc=">53547</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvNjAzMTQ=">60314</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMzg1MTY=">38516</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMzE4MDQ=">31804</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvNTY2OTA=">56690</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMTAwNzQ2">100746</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMTA0NDg5">104489</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMzg5ODU=">38985</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvNDUwMzI=">45032</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvNzUyNjM=">75263</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvNzc4MDE=">77801</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvOTQxMTI=">94112</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMzA2NDY=">30646</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMjMxNzU=">23175</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMjgzNzQ=">28374</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMjkyNzk=">29279</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMjk2ODI=">29682</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMjk2ODE=">29681</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMjk4Mjk=">29829</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMjk4Mjg=">29828</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvOTUyOTg=">95298</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvMjk2NjY=">29666</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvNDkzNjY=">49366</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvNzQzNDA=">74340</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvNzYzMDA=">76300</a>
    <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3VzZXJzY3JpcHRzLm9yZy9zY3JpcHRzL3Nob3cvNDUwMzI=">45032</a>
  </p>

<h3>Toolbars</h3>
  <ul>
    <li>right click on the toolbar, uncheck Web Development toolbar</li>
    <li>right click again, choose &#8216;Customize&#8217;, choose &#8216;Use Small Icons&#8217; and remove:
      <ul>
        <li>read it later</li>
        <li>search box</li>
        <li>zoom buttons</li>
        <li>home button</li>
        <li>bookmarks button</li>
        <li>FireBug button</li>
        <li>drag GreaseMonkey button to status bar</li>
      </ul>
      </li>
  </ul>

<h3>Cookies</h3>
  <p>
    click on CookieMonster at bottom of window, click View Cookies, show exceptions.<br />
    &#8216;Allow&#8217; sites you regularly visit<br />
    &#8216;Block&#8217; google properties
  </p>

<h3>Bookmarks menu -> Show all Bookmarks</h3>
  <p>
    &#8216;Import and Backup&#8217; -> Back up to json in old profile, Import &#8216;Choose File&#8217; in new</br>
    Same with ScrapBook &#8211; open sidebar, Tools, Import / Export, select all&#8230;
  </p>

<h3>Edit -> Preferences</h3>
  <ul>
    <li>
    General
      <ul>
        <li>&#8216;When Firefox starts&#8217;: Show my windows and tabs</li>
        <li>&#8216;Home Page&#8217;: about:blank</li>
      </ul>
    </li>
    <li>
    Tabs
      <ul>
        <li>check everything but &#8216;When I open a link in a new tab&#8217;</li>
      </ul>
    </li>
    <li>
    Applications
      <ul>
        <li>search for VLC, Windows, and QuickTime, change items to &#8216;Always Ask&#8217;</li>
      </ul>
    </li>
    <li>
    Privacy
      <ul>
        <li>check &#8216;Tell web sites I do not want to be tracked&#8217;</li>
        <li>select &#8216;Firefox will&#8217;: Use custom settings for history</li>
        <li>select &#8216;Keep until&#8217;: I close Firefox</li>
        <li>select &#8216;When using the location bar, suggest&#8217;: History</li>
      </ul>
    </li>
    <li>
    Security
      <ul>
        <li>uncheck &#8216;Remember passwords for sites&#8217;</li>
      </ul>
    </li>
    <li>
    Advanced -> Update
      <ul><li>uncheck &#8216;Search Engines&#8217;</li></ul>
    </li>
  </ul>
  
<h3>about:config</h3>
  <ul>
    <li>browser.autofocus false</li>
    <li>browser.dom.window.dom.enabled true (new)</li>
    <li>browser.history_expire_days 30</li>
    <li>browser.tabs.animate false</li>
    <li>browser.tabs.closeButtons 2</li>
    <li>browser.tabs.loadBookmarksInBackground true</li>
    <li>browser.tabs.loadDivertedInBackground true</li>
    <li>browser.tabs.selectOwnerOnClose false</li>
    <li>browser.zoom.full false</li>
    <li>browser.jsannoyances.disabled true (new)</li>
    <li>downbar.display.clearButton false</li>
    <li>downbar.display.mainButton false</li>
    <li>downbar.display.percent true</li>
    <li>downbar.function.useAnimation false</li>
    <li>network.http.pipelining true</li>
    <li>network.http.pipelining.maxrequests 8</li>
    <li>network.prefetch-next false</li>
  </ul>

<h3>~/.mozilla/firefox/[profile]/chrome</h3>
  <h4>userChrome.css</h4>

  <pre>&nbsp;
    @<span style="color: #003366; font-weight: bold;">namespace</span> url<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #009900; font-style: italic;">/* don't bold active tab title */</span>
    <span style="color: #009900; font-style: italic;">/* no longer works, argh */</span>
    tab<span style="color: #66cc66;">&#91;</span>selected=<span style="color: #3366CC;">"true"</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#123;</span> font-weight: normal !important; <span style="color: #66cc66;">&#125;</span>
&nbsp;
    <span style="color: #009900; font-style: italic;">/* stop TreeStyleTab's Sidebar theme from changing its color when in/active */</span>
    .<span style="color: #006600;">tabbrowser</span>-strip<span style="color: #66cc66;">&#91;</span>treestyletab-style=<span style="color: #3366CC;">"sidebar"</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#91;</span>treestyletab-mode=<span style="color: #3366CC;">"vertical"</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#123;</span>
      background-color: #ccc !important;
    <span style="color: #66cc66;">&#125;</span></pre>

  <h4>userContent.css</h4>

  <pre>&nbsp;
    <span style="color: #009900; font-style: italic;">/* indicate nofollow links with a dotted blue underline */</span>
    a<span style="color: #66cc66;">&#91;</span>rel~=nofollow<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#123;</span> border-bottom: 1px dotted blue !important; <span style="color: #66cc66;">&#125;</span></pre>

<p>
  Got any neat suggestions I&#8217;ve missed?
</p>
 <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1798" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2011/recreating-my-firefox-profile/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Craftsmanship Tour: New York Times</title>
		<link>http://push.cx/2011/craftsmanship-tour-new-york-times</link>
		<comments>http://push.cx/2011/craftsmanship-tour-new-york-times#comments</comments>
		<pubDate>Wed, 22 Jun 2011 18:07:54 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[craftsmanship tour]]></category>
		<category><![CDATA[idempotency]]></category>
		<category><![CDATA[journalism]]></category>
		<category><![CDATA[New York Times]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1762</guid>
		<description><![CDATA[In May, while visiting New York City, I dropped by the New York Times to code with Derek Willis and, impromptu, Dan Berko. I worked with both at the Washington Post (and saw many other familiar names on doors, online journalism is a small town). Derek&#8217;s got a great career arc. He climbed up the [...]]]></description>
			<content:encoded><![CDATA[<p>
In May, while visiting New York City, I dropped by the <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5ueXRpbWVzLmNvbQ==">New York Times</a> to code with <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3R3aXR0ZXIuY29tL2RlcmVrd2lsbGlz">Derek Willis</a> and, impromptu, <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3R3aXR0ZXIuY29tL2JlcmtvZA==">Dan Berko</a>. I worked with both at the <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=L3RhZy93YXNoaW5ndG9uLXBvc3Q=">Washington Post</a> (and saw many other familiar names on doors, online journalism is a small town).
</p>

<p>
Derek&#8217;s got a great career arc. He climbed up the ranks of journalism, covered Congress, and got involved in data-heavy projects. &#8220;Computer assisted reporting&#8221; is one of those terms that nobody quite loves but nobody&#8217;s successfully replaced (though it seems &#8220;database journalism&#8221; is gaining ground) and refers to collecting and analyzing data in databases. Derek got as interested in the &#8220;computers&#8221; as the &#8220;reporting&#8221; and has deliberately pushed his skills and career into software development. (*cough* sounds like a good topic for a <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2Jsb2cudGhlc2Nvb3Aub3Jn">quiet blog</a>, eh, Derek? *cough). I look at his <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9naXRodWIuY29tL2R3aWxsaXM=">GitHub profile</a> today and he&#8217;s been busily merging in contributions to his open source projects like his <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9naXRodWIuY29tL2R3aWxsaXMvdXNhdG9kYXktY2Vuc3Vz">USA Today Census gem</a>.
</p>

<p>
We started out the day looking around the FEC scraping code. In the States, the Federal Election Commission gives out lots of data from candidates filing required disclosure statements. We tidied up the database a little and then turned to the project for the day, which has just been publicly announced:
</p>

<blockquote>
Today we’re announcing the addition of paper campaign filings from Senate candidates and two party committees to our Campaign Finance API, which previously had only provided details of electronically filed reports. Now users can request and view the filings of any committee registered with the Federal Election Commission.

Unlike House and presidential candidates, current and would-be senators file their campaign reports first with the Secretary of the Senate, who then forwards them to the F.E.C. That agency then scans in the images from the paper filings and makes them available for viewing (an example). While an effort to require electronic filing for Senate candidates hasn’t gotten much traction this year, we have at least made the API’s set of filings more complete.
<cite><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL29wZW4uYmxvZ3Mubnl0aW1lcy5jb20vMjAxMS8wNi8wMi9wYXBlci1maWxpbmdzLw==">New in the Campaign Finance API: Paper Filings</a></cite>
</blockquote>

<p>
  The scraper was previously ignoring the paper-only reports, but we updated it to recognize and categorize them. The categorization was a huge bit of nostalgia for me: take the noisy and sometimes inconsistent provided categories and map them onto a standard set of database categories (form_type, in the screenshot in the announcement).
</p>

<p>
  When we ran the scraper, it would complain and halt each time it reached an unknown category. We&#8217;d add that to a mapping table and restart from that point, but it was frustrating to have to keep an eye on it. So we set the scraper to ignore records that it didn&#8217;t have a mapping for and warn about the problem. We set the scraper to run (and hit the amazing Shake Shack for burgers) and came back to find a list of missing mappings. After adding that, we ran the scraper again to fill in the missing entries.
</p>

<p>
  This worked because the scraper only added entries it didn&#8217;t already have recorded. The term for this is <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2MyLmNvbS9jZ2kvd2lraT9JZGVtcG90ZW50RGVzaWdu">idempotency</a>, and it&#8217;s useful from the level of individual functions up to large, fairly complex programs like web scrapers. Every program fails, having an idempotent approach to the problem means you don&#8217;t have to keep careful track of many types of failure because you can fix things and re-run your program without worrying about duplicate records or updating things twice.
</p> 

<p>
Derek had to run off to catch a train, so I dropped in on Dan Berko. He was on one of the Post&#8217;s several other &#8220;web innovation&#8221; teams while I was there, so we helped each other with code occasionally but didn&#8217;t spend a lot of time coding together.
</p>

<p>
The New York Times has large and well-maintained internal tools for reporters and editors. The reporters have a CMS for writing stories and the editors have a budgeting system for planning what goes where in the paper. We improved communcation between these two a bit, so the budgeting tool could refer to a story in the CMS and pull metadata from there instead of requiring an editor to re-input it. 
</p>

<p>
  The UI was simple: if the editor links a story, several fields should be grayed out and a checkbox should indicate the link. If the editor unchecks the box, the link is broken and the fields become editable again. This started out with two code paths &#8211; one for linking a story, one for unlinking &#8211; and making sure on pageload that the UI was in the proper state. We&#8217;d barely started writing that when we saw it could be implemented even simpler:
</p>

<pre>&nbsp;
disable_if_linked_to_cms: <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
  <span style="color: #003366; font-weight: bold;">var</span> checked = $<span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'asset_cms_id'</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">checked</span>;
  <span style="color: #66cc66;">&#91;</span><span style="color: #3366CC;">'asset_home_status_id'</span>, <span style="color: #3366CC;">'headline'</span>, etc.<span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">each</span><span style="color: #66cc66;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span>id<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
      $<span style="color: #66cc66;">&#40;</span>id<span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">disabled</span> = checked;
  <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>,
document.<span style="color: #006600;">observe</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'dom:loaded'</span>, <span style="color: #003366; font-weight: bold;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#123;</span>
  Event.<span style="color: #006600;">observe</span><span style="color: #66cc66;">&#40;</span><span style="color: #3366CC;">'asset_cms_id'</span>, <span style="color: #3366CC;">'click'</span>, Budget.<span style="color: #006600;">disable_if_linked_to_cms</span><span style="color: #66cc66;">&#41;</span>;
  Budget.<span style="color: #006600;">disable_if_linked_to_cms</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>;</pre>

<p>
When the checkbox is checked, all the form fields are disabled. When it&#8217;s unchecked, they&#8217;re not. The code runs on pageload and anytime the checkbox is toggled. I really liked this bit of code: we started out writing the simplest thing that came to mind, but soon we realized it could be reduced. The resulting code probably elicits a &#8220;So what, it&#8217;s not doing much?&#8221; reaction, which is far better than the previous &#8220;Now, let&#8217;s see, what&#8217;s this doing?&#8221; we would&#8217;ve had at first. The sign of the best code is that you immediately understand it, not that you have to stretch yourself to follow its solution.
</p>
 <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1762" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2011/craftsmanship-tour-new-york-times/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Now Featuring Monsters</title>
		<link>http://push.cx/2011/now-featuring-monsters</link>
		<comments>http://push.cx/2011/now-featuring-monsters#comments</comments>
		<pubDate>Sat, 18 Jun 2011 11:00:20 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Allabrilyn]]></category>
		<category><![CDATA[Fantasy Adventure Game]]></category>
		<category><![CDATA[grue]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[so play we all]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1783</guid>
		<description><![CDATA[The So Play We All theme this week was &#8220;core game objects&#8221; and the time budget was 3 hours. I did did well for myself, time to review the others&#8217; work &#8212; both of which included monsters. Luke did well this week as he started to build out his combat system, including party members who [...]]]></description>
			<content:encoded><![CDATA[<p>
The <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5zb3BsYXl3ZWFsbC5jb20=">So Play We All</a> theme this week was &#8220;core game objects&#8221; and the time budget was 3 hours. I did <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2Jsb2cub2Fxbi5jb20vMjAxMS9tYXBwaW5nLXRoZS13b3JsZA==">did well for myself</a>, time to review the others&#8217; work &mdash; both of which included monsters.
</p>

<p>
Luke <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2Jsb2cuZmFudGFzeWFkdmVudHVyZWdhbWUuY29tLzIwMTEvMDYvMTIvZGlyZS1iZWFycy1hbmQtbXlzdGVyaWVzLW9oLW15Lw==">did well</a> this week as he started to build out his combat system, including party members who (unless he&#8217;s hacked it in, but it doesn&#8217;t look that way) respond to locations and enemies. It&#8217;s a start at gameplay, though your choices are pretty limited so far. I like the idea in the blog post about having party members you can configure but not directly control, it reminds me of Ogre Battle.
</p>

<p>
Also, he&#8217;s started the storyline, including &#8220;the fact that the bear can’t seem to find you is important&#8221;. When you <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2ZhbnRhc3lhZHZlbnR1cmVnYW1lLmNvbS8=">play</a>, the bear enemy appears to be completely incapable of attacking you. Just for wild-ass guessing&#8217;s sake, I&#8217;m going to guess the player starts as some kind of ghost. We&#8217;ll see how I did when the storyline takes shape.
</p>

<p>
Jim&#8230; <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2Jsb2cuYWxsYWJyaWx5bi5jb20vY29udGVudC9jb250cm9sbGluZy1jb250cm9sbGVycw==">continued to work</a> on the controllers for his web framework, as he did <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvMjAxMS9zcHdhLXdlZWstMi1mdW5kaW5nLWFuZC1mb3Jtcw==">last week</a>. I felt like this:
</p>

<blockquote style="color: #e3e3e3; background-color: #000000; border-radius: 8px; font-family: courier, monospace;">
<p>&gt; Application creates CommandRouter and TemplateDisplay instances</p>

<p>I&#8217;m very happy for it.</p>

<p>&gt; Application retrieves Events from the CommandRouter for the current Post data (usually none)</p>

<p>So, it&#8217;s like how PHP populates $_GET and $_POST for you before invoking a script, but redundant.</p>

<p>&gt; Application retrieves Events from the CommandRouter for the current URI</p>

<p>Events are sounding awfully general purpose. Wasn&#8217;t this a game? I feel faint.</p>

<p>&gt; Application loops through the current events (events can be added while processing other events) and calls the CommandRouter->ProcessEvent() method for each one</p>

<p>It&#8217;s a generic message queueing system. The world is going dim&#8230;</p>

<p>&gt; CommandRouter creates any necessary controller and sub-display instance for the event and passes all data to any module event handlers registered for the current event</p>

<p>It is pitch black. You are likely to be eaten by a grue.</p>

<p>&gt; Created controllers determine models to use which add their data to the relevant Display objects (which are further applied to the TemplateDisplay instance)</p>

<p>No, really, a grue. It eats developers who don&#8217;t finish games.</p>

<p>&gt; Application renders the TemplateDisplay</p>

<p>The grue dies of boredom.</p>
</blockquote>

<p>
Jim <a href="">mentioned</a> he liked the Mortal Kombat drawing last week. I guess he didn&#8217;t click on it. It&#8217;s a link to a <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL21ha2VnYW1lcy50dW1ibHIuY29tL3Bvc3QvMTEzNjYyMzc2Ny9maW5pc2hpbmctYS1nYW1l">great article</a>, which includes:
</p>

<blockquote>
<p><b>3. DON’T ROLL YOUR OWN TECH IF YOU DON’T HAVE TO</b></p>

<p>
There are pros and cons to writing your own engine. But ask yourself, do you
really have to? Is what you want to do impossible to do with what’s already out
there or would you be reinventing the wheel? Of course, if you write your own
engine you can make it just perfect the way you like it. But be honest, how
often do you ever get past the engine to the game itself? Do you find yourself
making game engines more often than you do games?
</p>
</blockquote>

<p>
Bring the thunder, Jim.
</p> <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1783" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2011/now-featuring-monsters/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Software Craftsmanship Tour: Aidan Rogers</title>
		<link>http://push.cx/2011/software-craftsmanship-tour-aidan-rogers</link>
		<comments>http://push.cx/2011/software-craftsmanship-tour-aidan-rogers#comments</comments>
		<pubDate>Wed, 30 Mar 2011 04:08:59 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[craftsmanship tour]]></category>
		<category><![CDATA[interfaces]]></category>
		<category><![CDATA[object orientation]]></category>
		<category><![CDATA[open question]]></category>
		<category><![CDATA[software development]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1731</guid>
		<description><![CDATA[A few weeks ago I met up with Aidan Rogers to hack on some code. Aidan and I were coworkers at Cambrian House a few years ago. Aidan and I hacked away at adding a feature to a Web App That Shall Not Be Named. User authentication was handled by Facebook or Twitter, so the [...]]]></description>
			<content:encoded><![CDATA[<p>
A few weeks ago I met up with <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3R3aXR0ZXIuY29tL2FpZGFuX3JvZ2Vycw==">Aidan Rogers</a> to hack on some code. Aidan and I were coworkers at <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=L3RhZ3MvY2FtYnJpYW4taG91c2U=">Cambrian House</a> a few years ago. 
</p>

<p>
Aidan and I hacked away at adding a feature to a Web App That Shall Not Be Named. User authentication was handled by Facebook or Twitter, so the feature was to fetch and list their friendships from their social network. The code in <kbd>app/models/user.rb</kbd> was straightforward, taking an object from authentication:
</p>

<pre>&nbsp;
<span style="color: #808080; font-style: italic;"># Update the database with the user's current list of friends.</span>
<span style="color: #808080; font-style: italic;"># Compares a fresh list to the existing list to minimize database writes.</span>
def update_friends<span style="color: #66cc66;">&#40;</span>auth<span style="color: #66cc66;">&#41;</span>
  <span style="color: #808080; font-style: italic;"># fetch current list of friendships as hashes</span>
  provider_friendships = auth.<span style="">retrieve_friendships</span>
  <span style="color: #808080; font-style: italic;"># load already-stored friendships to hashes</span>
  stored_friendships = friendships.<span style="">send</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">"on_#{auth.provider}"</span><span style="color: #66cc66;">&#41;</span>.<span style="">map</span> <span style="color: #66cc66;">&#123;</span> |friend| <span style="color: #66cc66;">&#123;</span>:id =&gt; friend.<span style="">friend_id</span>, :name =&gt; friend.<span style="">friend_name</span><span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># compare the two lists of hashes</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># add any new friends to the database</span>
  <span style="color: #66cc66;">&#40;</span>provider_friendships - stored_friendships<span style="color: #66cc66;">&#41;</span>.<span style="">each</span> <span style="color: #b1b100;">do</span> |friend|
    friendships.<span style="">create</span>!<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#123;</span>
      :friend_id =&gt; friend<span style="color: #66cc66;">&#91;</span>:id<span style="color: #66cc66;">&#93;</span>,
      :friend_name =&gt; friend<span style="color: #66cc66;">&#91;</span>:name<span style="color: #66cc66;">&#93;</span>,
      :provider =&gt; auth.<span style="">provider</span>,
    <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #b1b100;">end</span>
&nbsp;
  <span style="color: #808080; font-style: italic;"># delete any removed friends from the database</span>
  <span style="color: #66cc66;">&#40;</span>stored_friendships - provider_friendships<span style="color: #66cc66;">&#41;</span>.<span style="">each</span> <span style="color: #b1b100;">do</span> |friend|
    friendships.<span style="">destroy_all</span><span style="color: #66cc66;">&#40;</span>:conditions =&gt; <span style="color: #66cc66;">&#123;</span> :friend_id =&gt; = friend<span style="color: #66cc66;">&#91;</span>:id<span style="color: #66cc66;">&#93;</span>, :friend_name =&gt; friend<span style="color: #66cc66;">&#91;</span>:name<span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #b1b100;">end</span>
end</pre>

<p>
That code isn&#8217;t very complicated, but it&#8217;s worth noting before you read the next snipped that we were both new to the Facebook/Twitter APIs and <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2MyLmNvbS9jZ2kvd2lraT9TcGlrZVNvbHV0aW9u">spiking</a> functionality rather than trying to write production quality code.
</p>

<p>
Keep that in mind as you read the code we added to the authentication object. It works, but it could definitely be better written (left as an exercise to the reader, because, well, we only spiked, so I haven&#8217;t actually written a better version to present).
</p>

<pre>&nbsp;
def retrieve_friendships
  <span style="color: #b1b100;">if</span> provider == <span style="color: #ff0000;">"facebook"</span>
    <span style="color: #808080; font-style: italic;"># made the Facebook API call</span>
    user = FbGraph::<span style="color: #006600;">User</span>.<span style="">me</span><span style="color: #66cc66;">&#40;</span>self.<span style="">data</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'credentials'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'token'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># map it to an array of hashes</span>
    <span style="color: #000066;">return</span> user.<span style="">friends</span>.<span style="">map</span> <span style="color: #b1b100;">do</span> |friend|
      <span style="color: #808080; font-style: italic;"># check against the db to load their id</span>
      existing = Authentication.<span style="">where</span><span style="color: #66cc66;">&#40;</span>:uid =&gt; friend.<span style="">identifier</span>, =
:provider =&gt; <span style="color: #ff0000;">'facebook'</span><span style="color: #66cc66;">&#41;</span>.<span style="">first</span>
      <span style="color: #66cc66;">&#123;</span> :friend =&gt; existing ? existing.<span style="">user</span> : nil,
        :provider_id =&gt; existing ? nil : friend.<span style="">identifier</span>,
        :provider =&gt; <span style="color: #ff0000;">'facebook'</span> <span style="color: #66cc66;">&#125;</span>
    <span style="color: #b1b100;">end</span>
  <span style="color: #b1b100;">elsif</span> provider == <span style="color: #ff0000;">"twitter"</span>
    <span style="color: #808080; font-style: italic;"># Returns only 20 users at a time - is it important enough at this = point to add all the code for iterating? (aidan)</span>
    <span style="color: #808080; font-style: italic;"># return Twitter.friends(nickname).users.map{ |friend| Hash[ :id =&gt; = friend.id, :name =&gt; friend.screen_name, :provider =&gt; 'twitter' ]}</span>
    <span style="color: #000066;">return</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span>
  <span style="color: #b1b100;">else</span>
    raise <span style="color: #ff0000;">"Refactor me"</span>
  <span style="color: #b1b100;">end</span>
end</pre>

<p>
Having the authentication object test what provider API it should be loading from is an obvious <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2MyLmNvbS9jZ2kvd2lraT9Db2RlU21lbGw=">code smell</a>, but it&#8217;s not the one I want to talk about.
</p>

<p>
There&#8217;s an implicit type in use. Aidan and I referred to it as a <kbd>FriendHash</kbd>, it&#8217;s a normalization for comparing friendship objects from the app&#8217;s database and from different API calls. FriendHash would be a data class with just a smidge of validation code to account for all three attributes.
</p>

<p>
I&#8217;ve noticed these sneaking around code in the interfaces between objects. I don&#8217;t quite have a name for them, but I realize it touches a bit on <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2MyLmNvbS9jZ2kvd2lraT9EZXNpZ25CeUNvbnRyYWN0">design by contract</a>. The part that smells to me is that this code is spread amongst many places that need to be updated in sync with each other (not that this is terribly better if you have a class for it, but at least you can grep for references to it). I&#8217;m not a big fan of data classes, so I don&#8217;t love this solution.
</p>

<p>
What really frustrates me is that I&#8217;ve got enough experience to have a tingling intuition when I am attempting to re-solve some problem that surely someone else has analyzed and offered solutions to, but my resesarch hasn&#8217;t turned anything up.
</p>

<p>
So I&#8217;m posting to hear what folks think of this situation. Have you read anyone writing about these quiet but complex data types at interfaces, or do you have ideas for how to address them?
</p>
 <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1731" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2011/software-craftsmanship-tour-aidan-rogers/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Retracting my JungleDisk Recommendation</title>
		<link>http://push.cx/2011/retracting-my-jungledisk-recommendation</link>
		<comments>http://push.cx/2011/retracting-my-jungledisk-recommendation#comments</comments>
		<pubDate>Sat, 19 Feb 2011 19:12:07 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[backups]]></category>
		<category><![CDATA[JungleDisk]]></category>
		<category><![CDATA[tarsnap]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1694</guid>
		<description><![CDATA[Over the last few years I&#8217;ve recommended JungleDisk to a lot of people, so a blog post is the most efficient way to retract that recommendation. I&#8217;ve been increasingly dissatisfied with it since Rackspace bought the company. They added a monthly fee on top of storage costs for no reason, stopped issuing source code to [...]]]></description>
			<content:encoded><![CDATA[<p>
Over the last few years I&#8217;ve recommended JungleDisk to a lot of people, so a blog post is the most efficient way to retract that recommendation.
</p>

<p>
I&#8217;ve been increasingly dissatisfied with it since Rackspace bought the company. They added a monthly fee on top of storage costs for no reason, stopped issuing source code to a standalone program for retrieving data, performance hasn&#8217;t kept up with my growth in usage (open dialog to choose which files to back up, get coffee), it does an 80MB download on every startup, backups of even a few K finish with a tens-of-megs metadata upload, and now they plan to reduce client-side functionality.
</p>

<blockquote>
<h3>2. New Web-based User Interface</h3>
In the spirit of flexibility and accessibility, the next release will have the configuration and setup totally managed via a web-based user interface vs. one that is incorporated into the computer’s operating system.  In one simple interface, you will be able to manage every user and computer in a secure web experience that is familiar regardless if you are managing a Windows, Mac or Linux machine.  This aspect of the update has been a huge undertaking for us because we want this to be a great user experience.  Luckily, we have some pretty amazing talent that is helping us to build a truly awesome UI.
<cite><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2Jsb2cuanVuZ2xlZGlzay5jb20vMjAxMS8wMS8yNi90aGUtcm9hZC1haGVhZC0yLw==">The Road Ahead</a> from the JungleDIsk blog</code>
</blockquote>

<p>
While JungleDisk used to sport "you don't have to trust us" encryption, this new UI means they'll need to keep a list of all of your files. And as much as I love the web, the desktop UI to JungleDisk is already painfully slow and clunky; the web adds network latency, browser overhead, and a much-reduced selection of widgets.
</p>

<p>
This is the last straw for me. After surveying the field I've settled on <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3RhcnNuYXAuY29t">tarsnap</a>. I'll write another post with more information on why I chose it and how I've set it up (it's a pretty low-level tool) when I've finished the big re-upload, cleaned up the remainders of JungleDisk, and settled into a regular rhythm.
</p> <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1694" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2011/retracting-my-jungledisk-recommendation/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Dropbox and Git Play Well Together</title>
		<link>http://push.cx/2011/dropbox-and-git</link>
		<comments>http://push.cx/2011/dropbox-and-git#comments</comments>
		<pubDate>Tue, 15 Feb 2011 04:57:42 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Dropbox]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[how to]]></category>
		<category><![CDATA[version control]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1684</guid>
		<description><![CDATA[Chrys Wu asked me my thoughts about how to have easy access to a software project she&#8217;s working on so that she can conveniently access them from the several computers she uses regularly. Not all of them can be set up as development machines, so a standard version control system can&#8217;t be used alone. That [...]]]></description>
			<content:encoded><![CDATA[<p>
<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2Nocnlzd3UuY29t">Chrys Wu</a> asked me my thoughts about how to have easy access to a software project she&#8217;s working on so that she can conveniently access them from the several computers she uses regularly. Not all of them can be set up as development machines, so a standard version control system can&#8217;t be used alone.
</p>

<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly93d3cuZHJvcGJveC5jb20vcmVmZXJyYWxzL05URTFNRGN3TVRBNE9RP3NyYz1nbG9iYWw5"><img src="http://push.cx/wp-content/uploads/2011/02/dropbox-logo.png" alt="" title="Dropbox logo" width="231" height="60" class="alignright size-full wp-image-1697" /></a>
<p>
That calls for a way to sync files, and <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly93d3cuZHJvcGJveC5jb20vcmVmZXJyYWxzL05URTFNRGN3TVRBNE9RP3NyYz1nbG9iYWw5">Dropbox</a> is by far the most convenient way to do so. Dropbox Just Works to copy files between computers, whether on Linux, OS, or Windows. Even an IT department that doesn&#8217;t want to install a development suite will probably be OK with it.
</p>

<p>
But software always <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3RvbS5wcmVzdG9uLXdlcm5lci5jb20vMjAwOS8wNS8xOS90aGUtZ2l0LXBhcmFibGUuaHRtbA==">calls for version control</a>, it&#8217;s essential to keep track of changes. Git happens to be the right version control software for her project, so here&#8217;s the steps we worked through to set up her environment.
</p>

<p>
First, she created her repository inside her Dropbox folder. We&#8217;ll call this the <kbd>dropbox</kbd> repo.
</p>

<pre>&nbsp;
desktop:~/Dropbox $ git init project
desktop:~/Dropbox $ <span style="color: #000066;">cd</span> project
desktop:~/Dropbox/project $ <span style="color: #808080; font-style: italic;"># create and commit first files</span></pre>

<p>
Now she has convenient access to her files across her computers, but there&#8217;s a pitfall: if she were to edit and commit to the <kbd>dropbox</kbd> repo on two machines that were offline, Dropbox would merge the git metadata in unpredictable ways. Each machine needs its own repository for work done in it, then changes can be deliberately pulled up to the authoritative Dropbox repository for integration. Edits done on a machine without git installed can be left in the Dropbox repo until they can be checked in, which works well enough for this scenario.
</p>

<p>
Creating a local repository is simple:
</p>

<pre>&nbsp;
laptop:~/ $ git clone ~/Dropbox/project
laptop:~/ $ git remote -v
origin  /home/username/Dropbox/project/ <span style="color: #66cc66;">&#40;</span>fetch<span style="color: #66cc66;">&#41;</span>
origin  /home/username/Dropbox/project/ <span style="color: #66cc66;">&#40;</span>push<span style="color: #66cc66;">&#41;</span>
laptop:~/ $ <span style="color: #000066;">cd</span> project
laptop:~/project/ $ git pull <span style="color: #808080; font-style: italic;"># to get the latest changes</span></pre>

<p>
The <kbd>laptop</kbd> repo shows that it knows about the <kbd>dropbox</kbd> repo, and a <kbd>git pull</kbd> will bring in any changes. But <kbd>git push</kbd> will give a <strong>giant error</strong>:
</p>

<pre>&nbsp;
laptop:~/project/ $ git push
Counting objects: <span style="color: #cc66cc;">157</span>, <span style="color: #b1b100;">done</span>.
Delta compression using up to <span style="color: #cc66cc;">2</span> threads.
Compressing objects: <span style="color: #cc66cc;">100</span>% <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">152</span>/<span style="color: #cc66cc;">152</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #b1b100;">done</span>.
Writing objects: <span style="color: #cc66cc;">100</span>% <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">157</span>/<span style="color: #cc66cc;">157</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #cc66cc;">982</span>.<span style="color: #cc66cc;">50</span> KiB, <span style="color: #b1b100;">done</span>.
Total <span style="color: #cc66cc;">157</span> <span style="color: #66cc66;">&#40;</span>delta <span style="color: #cc66cc;">44</span><span style="color: #66cc66;">&#41;</span>, reused <span style="color: #cc66cc;">0</span> <span style="color: #66cc66;">&#40;</span>delta <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch <span style="color: #b1b100;">in</span> a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require <span style="color: #ff0000;">'git reset --hard'</span> to match
remote: error: the work tree to HEAD.
remote: error:
remote: error: You can <span style="color: #000066;">set</span> <span style="color: #ff0000;">'receive.denyCurrentBranch'</span> configuration variable to
remote: error: <span style="color: #ff0000;">'ignore'</span> or <span style="color: #ff0000;">'warn'</span> <span style="color: #b1b100;">in</span> the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed <span style="color: #b1b100;">in</span> some
remote: error: other way.
remote: error:
remote: error: To squelch this message and still keep the default behaviour, <span style="color: #000066;">set</span>
remote: error: <span style="color: #ff0000;">'receive.denyCurrentBranch'</span> configuration variable to <span style="color: #ff0000;">'refuse'</span>.
To /home/username/Dropbox/project/
 ! <span style="color: #66cc66;">&#91;</span>remote rejected<span style="color: #66cc66;">&#93;</span> master -&gt; master <span style="color: #66cc66;">&#40;</span>branch is currently checked out<span style="color: #66cc66;">&#41;</span>
error: failed to push some refs to <span style="color: #ff0000;">'/home/username/Dropbox/project/'</span></pre>

<p>
This is one of git&#8217;s more <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3N0ZXZlLXBhcmtlci5vcmcvYXJ0aWNsZXMvb3RoZXJzL3N0ZXBoZW5zb24vaG9sZWhhd2cuc2h0bWw=">unix-like</a> error messages, in that it makes sense once you already understand it and happens because git is an incredibly powerful, flexible tool that assumes you know what you&#8217;re doing. Let&#8217;s walk through the error.
</p>

<p>
Everything down to the &#8220;Total&#8221; line is git giving you information about how it&#8217;s packaging the data to send between repositories and is normal.
</p>

<p>
The first paragraph is warning that you&#8217;re pushing code to what&#8217;s currently being worked on in the other repository (the &#8220;checked out branch&#8221;). Git can&#8217;t know that the other one is just files sitting around &#8211; what if it&#8217;s some other user&#8217;s, and he&#8217;s in the middle of editing things? Well, if someone else might be using it, we can&#8217;t update the files in the working copy, because it would trash his work. But if git doesn&#8217;t do that, the remote repo knows that it&#8217;s not at HEAD &#8211; meaning the next commit will confusingly create a branch.
</p>

<p>
The second paragraph is saying &#8220;If you&#8217;re sure you know what you&#8217;re doing, you can configure the remote repository to let you do this.&#8221;
</p>

<p>
The third is saying &#8220;Or you can just tell me to shut up.&#8221;
</p>

<p>
Finally, the last few lines are git attempting finish the push. It says &#8220;OK, with everything ready, I&#8217;m going to push&#8221; and then &#8220;Wait, I couldn&#8217;t push from my master to the remote master&#8221; and &#8220;you told me to push at least one branch and at least one failed&#8221; (in this case, excatly 1 and 1). In short, git is refusing to take the risk of maybe screwing up work.
</p>

<p>
There are two responses.
</p>

<p>
The first is to make the Dropbox repository a &#8220;bare repository&#8221;. That means it will have all the history of the project, but no checked-out, editable copies of the project. That would stop you from conveniently reading the files wherever you happened to be, though. When you have a repository on GitHub, that copy on their servers is a bare repo &#8211; GitHub doesn&#8217;t have any interest in editing the files and doesn&#8217;t want you to have this problem.
</p>

<p>
The second is simpler, and what you want to do for this situation. Pulling changes is always OK, because git knows you know what you&#8217;re doing with the current repo. So, from the <kbd>dropbox</kbd> repo:
</p>

<pre>&nbsp;
laptop:~/Dropbox/project $ git remote add laptop ~/project
laptop:~/Dropbox/project $ git pull laptop master <span style="color: #808080; font-style: italic;"># note that you have to name what branch to pull from</span>
From /home/username/project
 * branch           master -&gt; FETCH_HEAD</pre>

<p>
Git reports the path to the repo it&#8217;s pulling from and which branches it was able to update, in this case <kbd>master</kbd> from what it found on the remote <kbd>HEAD</kbd>. Success!
</p>

<p>
All that&#8217;s needed to add more machines is to run the <kbd>git clone</kbd> on them and then, from the <kbd>dropbox</kbd> repo, add them as remotes for pulling changes.
</p>

<p>
Dropbox and git play nicely when you need their different strengths.
</p> <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1684" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2011/dropbox-and-git/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Craftsmanship Tour: Jim Ray</title>
		<link>http://push.cx/2011/craftsmanship-tour-jim-ray</link>
		<comments>http://push.cx/2011/craftsmanship-tour-jim-ray#comments</comments>
		<pubDate>Mon, 14 Feb 2011 00:34:55 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[craftsmanship tour]]></category>
		<category><![CDATA[Devise]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1688</guid>
		<description><![CDATA[Last Tuesday I spent the afternoon with Jim Ray at the excellent Hooked coffeeshop in Denver, CO (and then I spent the next several days sick from a bad meal and recovering, so this post got delayed). We worked on FindAPair, a small web app he&#8217;s developing with Jeff Powell. Developers can list their city [...]]]></description>
			<content:encoded><![CDATA[<p>
Last Tuesday I spent the afternoon with <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3R3aXR0ZXIuY29tL2ppbWlyYXk=">Jim Ray</a> at the excellent <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5teXNwYWNlLmNvbS9ob29rZWRvbmNvbGZheA==">Hooked</a> coffeeshop in Denver, CO (and then I spent the next several days sick from a bad meal and recovering, so this post got delayed).
</p>

<p>
We worked on <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9naXRodWIuY29tL2ppbWlyYXkvZmluZGFwYWly">FindAPair</a>, a small web app he&#8217;s developing with <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5ub3NjZXRpcHN1bS5jb20v">Jeff Powell</a>. Developers can list their city and link to their Twitter and GitHub profiles to find other devs to pair with. (Yeah, this basic idea felt <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL25lYXJieWdhbWVycy5jb20=">pretty familiar</a>.)
</p>

<p>
First, Jim and I <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9naXRodWIuY29tL2ppbWlyYXkvZmluZGFwYWlyL2NvbW1pdC9jZmE5OGZmMmZmODliNzY4N2QxZDk5ZDdkNjhjYmEzNWY2ZjFkYTNl">added</a> some acceptance tests using <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9naXRodWIuY29tL2NhdmFsbGUvc3RlYWs=">Steak</a> to test profile editing. Steak is a DSL for acceptance in BDD, but closer to Ruby code than the popular <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2N1a2VzLmluZm8v">Cucumber</a>. Jim explained he chose Steak because this project does not have a non-technical customer who&#8217;d read, verify, and help write specs. Cucumber&#8217;s translation between text files and method calls would be unnecessary complexity.
</p>

<p>
FindAPair uses the wonderful <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9naXRodWIuY29tL3BsYXRhZm9ybWF0ZWMvZGV2aXNl">Devise</a> library, so we followed <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9naXRodWIuY29tL3BsYXRhZm9ybWF0ZWMvZGV2aXNlL3dpa2kvSG93LVRvOi1BbGxvdy11c2Vycy10by1zaWduX2luLXVzaW5nLXRoZWlyLXVzZXJuYW1lLW9yLWVtYWlsLWFkZHJlc3M=">the steps on the wiki</a> to allow people to log in by username as well as email address. It went pretty well, but we needed to do a little tweaking for Rails 3. Of course, we contributed back to the docs. One of the nice things about GitHub is how frictionless it is to share these small improvements.
</p>

<p>
Another interesting bit of coding was planning the URL structure of the site. The two major resources are users and the cities they live in. Jim wanted to have really simple URLs like <kbd>findapair.me/jimiray</kbd> or <kbd>findapair.me/denver</kbd>. He didn&#8217;t want to overlap the namespaces, but he couldn&#8217;t decide between them. As he was explaining the problem I thought back to the early days of the web and suggested putting cities at the root and users at <kbd>findapair.me/~jimiray</kbd>. Jim laughed, decided the audience was nerdy enough to remember it, so we <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9naXRodWIuY29tL2ppbWlyYXkvZmluZGFwYWlyL2NvbW1pdC82N2QxNTgxNGZkMWNlYmEzODY3ODA4N2NlYjNhYjk2ZDNkYWZiZmQwI2RpZmYtMg==">committed it</a>.
</p>

<p>
I&#8217;m not going to recount all the little things we did, but it was a fun afternoon building what could be a great resource.
</p>

<p>
While I was programming with Jim, I was reminded of the importance of studying. I knew a lot more vim commands than Jim, but it&#8217;s not because I&#8217;m any smarter. When I started learning vim I quickly realized it was a far bigger topic than I could absorb at once, so I only learned enough to take care of my daily routine. After I was comfortable with that, I started reading the vim manual, but I read at most one chapter a week. Read a little, experiment, give it time to settle, refresh my reading in a few days, and then move on to something else. In the decade since then, I still watch for new information about vim, reading the <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3JlZGRpdC5jb20vci92aW0=">vim subreddit</a> and Twitter accounts like <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3R3aXR0ZXIuY29tL2xlYXJudmlt">learnvim</a> and <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3R3aXR0ZXIuY29tL2RvdHZpbXJj">dotvimrc</a>. It&#8217;s easy to skip over the stuff I already know. It&#8217;s easier to earn in small amounts over years than read one book and hope to retain everything.
</p>
 <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1688" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2011/craftsmanship-tour-jim-ray/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Craftsmanship Tour: David W. Allen</title>
		<link>http://push.cx/2011/craftsmanship-tour-david-w-allen</link>
		<comments>http://push.cx/2011/craftsmanship-tour-david-w-allen#comments</comments>
		<pubDate>Wed, 05 Jan 2011 03:50:18 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[craftsmanship tour]]></category>
		<category><![CDATA[graphs]]></category>
		<category><![CDATA[NearbyGamers]]></category>
		<category><![CDATA[software craftsmanship]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1647</guid>
		<description><![CDATA[I&#8217;m in Grand Junction, Colorado because it seemed as good as any a place to start traveling. I have family in Denver and plans to ski, so why not tour the state a while? Once I knew I was coming to Grand Junction, I remembered GitHub can be searched by location and I got curious, [...]]]></description>
			<content:encoded><![CDATA[<p>
I&#8217;m in Grand Junction, Colorado because it seemed as good as any a place to start traveling. I have family in Denver and plans to ski, so why not tour the state a while? Once I knew I was coming to Grand Junction, I remembered GitHub can be searched by location and I got curious, so I did the search.
</p>

<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvd3AtY29udGVudC91cGxvYWRzLzIwMTEvMDEvZ2l0aHViX3NlYXJjaC5wbmc="><img src="http://push.cx/wp-content/uploads/2011/01/github_search.png" alt="" title="GitHub search for users in Grand Junction" width="532" height="238" class="aligncenter size-full wp-image-1656 important" /></a>

<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvd3AtY29udGVudC91cGxvYWRzLzIwMTEvMDEvSU1HXzM5NzNfbW9kaWZpZWQuanBn"><img src="http://push.cx/wp-content/uploads/2011/01/IMG_3973_modified-150x150.jpg" alt="" title="Grand Valley from Colorado National Monument" width="150" height="150" class="alignright size-thumbnail wp-image-1663" /></a>
<p>
One result? If there&#8217;d been a hundred people I&#8217;d have been done right there, but if there&#8217;s exactly one person, well, why not say hi? So I sent an email that I think sounded like this:
</p>

<blockquote>
I realize I&#8217;m a complete stranger and the idea of wandering into people&#8217;s offices to work with them for a day sounds perfectly ridiculous, but would you like to grab coffee, talk code, do some pair programming?
</blockquote>

<p>
Perhaps I didn&#8217;t come off quite so badly because <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2Rhdmlkd2FsbGVuLm5ldC8=">David</a> said &#8220;what the hell&#8221; and invited me to meet him for his workday at <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3RyYWRlcnNjb2ZmZWVhbmR0ZWEuY29tLw==">Traders Coffee</a>.
</p>

<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvd3AtY29udGVudC91cGxvYWRzLzIwMTEvMDEvU1RHXzQwODdfbW9kaWZpZWQuanBn"><img src="http://push.cx/wp-content/uploads/2011/01/STG_4087_modified-150x150.jpg" alt="" title="Colorado National Monument" width="150" height="150" class="alignright size-thumbnail wp-image-1662" /></a>
<p>
A side story: I happened to arrive before him and was looking around for him, and couldn&#8217;t see him. But I saw a woman surfing <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3N0YWNrb3ZlcmZsb3cuY29t">Stack Overflow</a>! I thought maybe this was someone David knew and invited along, so I had an awkward conversation where it quickly became clear she had no idea who I was or why I was introducing myself. If I&#8217;d been thinking quicker I&#8217;d have invited her to join us or at least given a business card, but my generic nerdly social phobia overwhelmed me and I excused myself. If you&#8217;re reading this and someone interrupted your Stack Overflow session to ask if you knew a guy you&#8217;d never heard of, sorry for the confusion, but if you&#8217;d like to grab coffee, talk code, maybe do some pair programming, I&#8217;m in town until Friday afternoon.
</p>

<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvd3AtY29udGVudC91cGxvYWRzLzIwMTEvMDEvSU1HXzQwNjRfbW9kaWZpZWQuanBn"><img src="http://push.cx/wp-content/uploads/2011/01/IMG_4064_modified-150x150.jpg" alt="" title="Rocks in a frozen stream" width="150" height="150" class="alignright size-thumbnail wp-image-1659" /></a>
<p>
As David and I sipped delicious lattes, I learned that he&#8217;s a mechanical engineer who got into software development around ten years ago as his job changed. He&#8217;s self-taught, he cracked the books and started experimenting. Along the way he attended some <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5jb25zdHJ1eC5jb20vUGFnZS5hc3B4P25pZD0xMg==">Construx Seminars</a>. Construx is the software firm started by <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TdGV2ZV9NY0Nvbm5lbGw=">Steve McConnell</a>, the giant who strides above programmers bestowing books of wisdom and lore, so that gave David a good grounding.
</p>

<p>
A lot of our conversation was about how David has found it hard to improve his craft without other, ideally better, programmers around to work with. It&#8217;s referenced by the community aspect of the <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL21hbmlmZXN0by5zb2Z0d2FyZWNyYWZ0c21hbnNoaXAub3JnLw==">Software Craftsmanship Manifesto</a>. Programmers improve their craft by improving each other&#8217;s craft.
</p>

<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvd3AtY29udGVudC91cGxvYWRzLzIwMTEvMDEvSU1HXzQwMTFfbW9kaWZpZWQuanBn"><img src="http://push.cx/wp-content/uploads/2011/01/IMG_4011_modified-150x150.jpg" alt="" title="Chapel with birds nesting on roof" width="150" height="150" class="alignright size-thumbnail wp-image-1658" /></a>
<p>
As an example, David told me about his startup project <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy52ZWxvZ3JhZi5jb20=">veloGraf</a>. He and another developer are using graph algorithms to analyze social networks and I soon realized I only know enough graph theory to hang onto the ankles of the conversation. I hadn&#8217;t thought about it before, but David pointed out that <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL25lYXJieWdhbWVycy5jb20vdGFncw==">game tags</a> on NearbyGamers form a highly cyclical graph. Gamers add edges to the graph by listing what games they&#8217;re interested in playing and tags self-referentially describe themselves (eg. <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL25lYXJieWdhbWVycy5jb20vdGFncy9EdW5nZW9uc18mIzAzODtfRHJhZ29ucw==">Dungeons and Dragons</a> is tagged as a an <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL25lYXJieWdhbWVycy5jb20vdGFncy9EdW5nZW9uc18mIzAzODtfRHJhZ29ucw==">RPG</a>).
</p>

<p>
I demoed the site&#8217;s most computationally-expensive page, which shows <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL25lYXJieWdhbWVycy5jb20vbmVhcmJ5L0hhcmtpbnMvZ2FtZXJz">gamers who share tags, sorted by distance</a>. This page required some hacking to avoid a gigantic couple of joins that would&#8217;ve dragged in most of the rows in the RDBMS, but David chuckled because it&#8217;s the sort of problem a proper graph database doesn&#8217;t even notice. He&#8217;s tracking millions of nodes with many times more edges in order to extract interesting connections. The simple analyses he pointed out flaws in common algorithms that were <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3NpdmVycy5vcmcvb2J2aW91cw==">obvious</a> to him but surprising to me. I managed to give him some fodder for experiments to improve his algorithms, which says more about the value of a little collaboration than it does my graph chops.
</p>

<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvd3AtY29udGVudC91cGxvYWRzLzIwMTEvMDEvSU1HXzQwMDVfbW9kaWZpZWQuanBn"><img src="http://push.cx/wp-content/uploads/2011/01/IMG_4005_modified-150x150.jpg" alt="" title="Main St. sculpture" width="150" height="150" class="alignright size-thumbnail wp-image-1657" /></a>
<p>
David told me a tale of (mild) woe from a previous job. An experienced cowbody coder was developing the core of a product while supposedly mentoring interns. In reality, they were restricted to working on small, ancillary tasks so as not to destabilize the core or distract the cowboy. How do you fix this?
</p>

<p>
My best guess (share yours in the comments, please &#8211; it&#8217;s not an uncommon scenario) was to task the interns with adding automated testing. The cowboy will think of it as menial work, but the interns will be exposed to the whole system and have reasons to have conversations with him. And probably better to start with acceptance testing than unit testing to preempt the cowboy from whining that using unit tests to verify that his code works (as opposed to hack and hope and oh yeah, I forgot those two things were related) slows down his brilliance.
</p>

<p>
There&#8217;s a complacency I&#8217;ve seen that&#8217;s sort of related to the <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5wYXVsZ3JhaGFtLmNvbS9hdmcuaHRtbA==">Blub Paradox</a>. When a programmer succeeds at building their first product or two, they often get an panglossian sense of competence. They may think, &#8220;I&#8217;m good at my job, there&#8217;s people telling me I should learn these things, but I&#8217;m good at my job without them, ipso facto I don&#8217;t need to learn more.&#8221; Unless they&#8217;re around a noticeably better programmer or especially introspective, they may never realize how much more there is to learn and the possibility of much greater skill.
</p>

<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvd3AtY29udGVudC91cGxvYWRzLzIwMTEvMDEvSU1HXzQwOTNfbW9kaWZpZWQuanBn"><img src="http://push.cx/wp-content/uploads/2011/01/IMG_4093_modified-150x150.jpg" alt="" title="Pedestrian bridge across I70" width="150" height="150" class="alignright size-thumbnail wp-image-1660" /></a>
<p>
I think this is where <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5zb2Z0d2FyZS10aG91Z2h0cy5jb20vMjAwOS8wOC9uZXQtbmVnYXRpdmUtcHJvZHVjaW5nLXByb2dyYW1lci5odG1s">net negative producing programmers</a> come from. I joined a project with an NNPP once. I watched all commits to the repository (everybody does this, right?) and I realized nearly his every commit added a bug or the strong potential for future problems. There was feedback available in the rising bug count and frustration of trying to improve the codebase, but he didn&#8217;t have the experience to know that this experience was abnormal. (Or at least improvable.) As I and other developers started cleaning up the code, he recognized what had been happening and decided to reinvest in his career by attending training.
</p>

<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvd3AtY29udGVudC91cGxvYWRzLzIwMTEvMDEvSU1HXzQwOTVfbW9kaWZpZWQuanBn"><img src="http://push.cx/wp-content/uploads/2011/01/IMG_4095_modified-150x150.jpg" alt="" title="Cross-country skiing on Grand Mesa" width="150" height="150" class="alignright size-thumbnail wp-image-1661" /></a>
<p>
I think this is why the nascent software craftsmanship movement has such potential. Programmers need to make steady improvement, however small, a core value of the profession. Currently there&#8217;s a &#8220;well, it works&#8221; when practice and mindful improvement could be a precept. The likeliest way I see that happening is masters of the craft mentoring apprentices. Every craft has its share of &#8220;just get it done&#8221;, but it doesn&#8217;t have to be the dominant culture.
</p>

<p>
<b>Update:</b> David has <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2Rhdmlkd2FsbGVuLm5ldC8yMDExLzAxL3NvZnR3YXJlLWNyYWZ0c21hbnNoaXAv">blogged his thoughts</a> on our wide-ranging conversation.
</p> <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1647" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2011/craftsmanship-tour-david-w-allen/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>XML Crash Course</title>
		<link>http://push.cx/2010/xml-crash-course</link>
		<comments>http://push.cx/2010/xml-crash-course#comments</comments>
		<pubDate>Fri, 17 Dec 2010 13:53:45 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[Star Trek]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1617</guid>
		<description><![CDATA[A non-nerdy friend of mine (yes, they exist, moving on) changed jobs at her company last week and had a question: So, it appears that i will have to learn how to use XML for my job. What would you suggest? And by &#8220;suggest&#8221;, i mean, &#8220;talk to me like i&#8217;m four.&#8221; I suggest you [...]]]></description>
			<content:encoded><![CDATA[<p>
A non-nerdy friend of mine (yes, they exist, moving on) changed jobs at her company last week and had a question:
</p>

<blockquote>
So, it appears that i will have to learn how to use XML for my job. What would you suggest? And by &#8220;suggest&#8221;, i mean, &#8220;talk to me like i&#8217;m four.&#8221;
</blockquote>

<p>
I suggest you get a better description of what you need to learn because they didn&#8217;t give you enough info. XML is a really general tool used in a lot of different things. (Some of us nerds hate XML and would prefer to see different things in its place, but knowing that doesn&#8217;t help you learn XML so I&#8217;m not going to talk about it except to finish with a terrible joke.)
</p>

<p>
XML is a way of marking up data. Imagine I have a catalog card for the (excellent) book I am rereading now:
</p>

  <blockquote>
  <a href=http://www.amazon.com/dp/0465067107/?tag=pushcx-20"">The Design of Everyday Things</a><br />
  Donald A. Norman<br />
  272p, 8.3 x 5.5 x 0.8<br />
<br />
  Anybody who has ever complained that &#8220;they don&#8217;t make things like they
  used to&#8221; will immediately connect with this book. Norman&#8217;s thesis is
  that when designers fail to understand the processes by which devices
  work, they create unworkable technology.
<br />
  978-00465067107<br />
  TS171.4 .N67 2002<br />
  </blockquote>

<p>
It&#8217;s a bunch of data. Now, you are a human. You have vast life experience and your brain is a massively parallel neural network, so you are excellent at pattern matching. You know which bits of data are the title or the description or the LOC number, and you&#8217;d know this even if you weren&#8217;t old enough to have used a physical card catalog (oh god we&#8217;re decrepit, why didn&#8217;t I use an iPhone or a pop star as an example?).
</p>

<p>
Computers suck at this. They like to have their data explained to them. XML is one, fairly human-readable way of doing so.
</p>

<p>
XML would &#8220;mark up&#8221; the card by labeling the different fields of information.
</p>

<pre>&nbsp;
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;card<span style="font-weight: bold; color: black;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;title<span style="font-weight: bold; color: black;">&gt;</span></span></span>The Design of Everyday Things<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/title<span style="font-weight: bold; color: black;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;author<span style="font-weight: bold; color: black;">&gt;</span></span></span>Donald A. Norman<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/author<span style="font-weight: bold; color: black;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;pagecount<span style="font-weight: bold; color: black;">&gt;</span></span></span>272<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/pagecount<span style="font-weight: bold; color: black;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;dimensions</span> <span style="color: #000066;">units</span>=<span style="color: #ff0000;">"inches"</span><span style="font-weight: bold; color: black;">&gt;</span></span>
    <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;height<span style="font-weight: bold; color: black;">&gt;</span></span></span>8.3<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/height<span style="font-weight: bold; color: black;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;width<span style="font-weight: bold; color: black;">&gt;</span></span></span>5.5<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/width<span style="font-weight: bold; color: black;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;depth<span style="font-weight: bold; color: black;">&gt;</span></span></span>0.8<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/depth<span style="font-weight: bold; color: black;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/dimensions<span style="font-weight: bold; color: black;">&gt;</span></span></span>
&nbsp;
  <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;description<span style="font-weight: bold; color: black;">&gt;</span></span></span>
  Anybody who has ever complained that &quot;they don't make things like they
  used to&quot; will immediately connect with this book. Norman's thesis is
  that when designers fail to understand the processes by which devices
  work, they create unworkable technology.
  <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/description<span style="font-weight: bold; color: black;">&gt;</span></span></span>
&nbsp;
  <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;isbn</span>-<span style="color: #cc66cc;">13</span><span style="font-weight: bold; color: black;">&gt;</span></span>978-00465067107<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/isbn</span>-<span style="color: #cc66cc;">13</span><span style="font-weight: bold; color: black;">&gt;</span></span>
  <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;loc</span>_number<span style="font-weight: bold; color: black;">&gt;</span></span>TS171.4 .N67 2002<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/loc</span>_number<span style="font-weight: bold; color: black;">&gt;</span></span>
<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/card<span style="font-weight: bold; color: black;">&gt;</span></span></span></pre>

<p>
The bits in angle brackets are called &#8220;tags&#8221;. It&#8217;s easy to tell a computer program to look for the &lt;title&gt; tag and save that to a particular field in a database, or display it on a web page, or whatever.
</p>

<p>
There are also &#8220;attributes&#8221;, like the &#8216;units=&#8221;inches&#8221;&#8216; on the &lt;dimensions&gt; tag. They&#8217;re usually used to describe the way the data is formatted.
</p>

<p>
Tags can be nested &#8211; notice everything is in a &lt;card&gt; tag and the measurements are nested in the &lt;dimensions&gt; tag. Let&#8217;s make one more nesting:
</p>

<pre>&nbsp;
  <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;authorlist<span style="font-weight: bold; color: black;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;author<span style="font-weight: bold; color: black;">&gt;</span></span></span>Donald A. Norman<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/author<span style="font-weight: bold; color: black;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/authorlist<span style="font-weight: bold; color: black;">&gt;</span></span></span></pre>

<p>
This book only has one author, but there are lots of books with multiple authors, like <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2RwLzA0NDA1Mzk4MTEvP3RhZz1wdXNoY3gtMjA=">The Illuminatus Trilogy</a>:
</p>

<pre>&nbsp;
  <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;authors<span style="font-weight: bold; color: black;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;author<span style="font-weight: bold; color: black;">&gt;</span></span></span>Robert Anton Wilson<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/author<span style="font-weight: bold; color: black;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;author<span style="font-weight: bold; color: black;">&gt;</span></span></span>Robert Shea<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/author<span style="font-weight: bold; color: black;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;author<span style="font-weight: bold; color: black;">&gt;</span></span></span>fnord<span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/author<span style="font-weight: bold; color: black;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="font-weight: bold; color: black;">&lt;/authors<span style="font-weight: bold; color: black;">&gt;</span></span></span></pre>

<p>
The design decisions of what tags to invent, how to nest them, and how to format data inside them is called a &#8220;schema&#8221;. XML files should each have a schema to eliminate the Dread Pirate Ambiguity. Is it &#8220;Robert Shea&#8221; or &#8220;Shea, Robert&#8221;? Or should we break it out into &lt;first-name&gt; and &lt;last-name&gt; tags, but then how would we deal with a book by Prince, when he even deigns to use an alphabet at all? Either you adopt a schema or you create your own, and hopefully you spend a lot of time thinking about all these weird things that can go wrong because it&#8217;s painful to have to change the schema and get everybody to agree to use the new thing.
</p>

<p>
The only other major concept is &#8220;validity&#8221;, which means making sure that tags are written properly (no &#8220;&lt;auth Robert Shea&lt;/author&gt;&#8221; or other typos) and used properly (no &#8220;&lt;author&gt;Robert Shea and Robert Anton Wilson&lt;/author&gt;&#8221;). Programmers, being a lazy and untrustworthy lot (and our XML tools often being big pains in the ass), often slap XML files together by hand and generate subtly invalid XML.
</p>

<p>
XML gets used for a huge amount of stuff nowadays because, despite some shortcomings (the big ones being verbosity, the difficulty of validity, and a lot of crappy programming tools), it&#8217;s a decent way of sharing data. And you don&#8217;t even have to know much about the schema to look at a file and start pulling data out of it.
</p>

<p>
If you&#8217;ve ever used a feed reader to follow a blog, those feeds it reads are stored in XML. In your browser, pull up my <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvZmVlZA==">blog feed</a>, click the View menu, and choose View Source. You&#8217;ll see the XML describing my recent posts as &lt;item&gt;s and, inside each, the text of each post in a &lt;description&gt;.
</p>

<p>
A little confusingly, that text is marked up with HTML, which is very similar to XML. XML and HTML are basically brothers, they&#8217;re based on the same older work (SGML), except that XML is like the Borg and tried to assimilate HTML in the early &#8217;00s (XHTML) and then the Federation (web nerds) realized that was a crappy idea and set off at maximum warp (let&#8217;s go build some awesome things and let the documentation catch up later) in a different direction (HTML5) and soon it&#8217;ll be holodecks for everybody (canvas, video, audio tags) and fire photon torpedoes at the Ferengi (Flash). <em>Exactly</em> like that.
</p>

<p>
So there&#8217;s a crash course in XML. I can&#8217;t tell you a lot more because I don&#8217;t know what your job will have you do with it. Saying they use XML is not much better than saying they use electricity. I know that you&#8217;re probably going to take some data from one place, format it, and put it in some other place but that&#8217;s a such a vague job description it even applies to those guys with the vacuum trucks who empty latrines (a metaphor that will become increasingly rich, predictive, and pungent to you the more time you spend with XML).
</p>

<p>
Questions?
</p>
 <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1617" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2010/xml-crash-course/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Craftsmanship Tour: 8th Light</title>
		<link>http://push.cx/2010/craftsmanship-tour-8th-light</link>
		<comments>http://push.cx/2010/craftsmanship-tour-8th-light#comments</comments>
		<pubDate>Wed, 15 Dec 2010 21:48:16 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[8th Light]]></category>
		<category><![CDATA[Clojure]]></category>
		<category><![CDATA[craftsmanship]]></category>
		<category><![CDATA[craftsmanship tour]]></category>
		<category><![CDATA[Groupon]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Limelight]]></category>
		<category><![CDATA[refactoring]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1601</guid>
		<description><![CDATA[The second stop on my craftsmanship tour was last Friday at 8th Light. They&#8217;re a local Chicago consultancy that&#8217;s active in the software craftsmanship community, especially in building the new Chicago SC group. I started out pairing with Colin Jones, which was a bit lucky because he&#8217;s also a vim user. After I shared the [...]]]></description>
			<content:encoded><![CDATA[<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvd3AtY29udGVudC91cGxvYWRzLzIwMTAvMTIvOHRobGlnaHQtbG9nby5wbmc="><img src="http://push.cx/wp-content/uploads/2010/12/8thlight-logo.png" alt="" title="8th Light logo" width="99" height="103" class="alignright size-full wp-image-1607 right" /></a>
<p>
The second stop on my <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=L2NyYWZ0c21hbnNoaXAtY2FsZW5kYXI=">craftsmanship tour</a> was last Friday at <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovLzh0aGxpZ2h0LmNvbQ==">8th Light</a>. They&#8217;re a local Chicago consultancy that&#8217;s active in the <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5zb2Z0d2FyZWNyYWZ0c21hbnNoaXAub3Jn">software craftsmanship</a> community, especially in building the new <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2dyb3Vwcy5nb29nbGUuY29tL2dyb3VwL2NoaXNj">Chicago SC group</a>.
</p>

<p>
I started out pairing with <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3R3aXR0ZXIuY29tL3RycHRjb2xpbg==">Colin Jones</a>, which was a bit lucky because he&#8217;s also a vim user. After I <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3R3aXR0ZXIuY29tLyMhL3B1c2hjeC9zdGF0dXMvMTMyODM1ODAzODU5NTk5MzY=">shared</a> the joy of <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy52aW0ub3JnL3NjcmlwdHMvc2NyaXB0LnBocD9zY3JpcHRfaWQ9Mzk=">matchit.vim</a> we got down to the task at hand.
</p>

<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvd3AtY29udGVudC91cGxvYWRzLzIwMTAvMTIvZ3JvdXBvbl9sb2dvLnBuZw=="><img src="http://push.cx/wp-content/uploads/2010/12/groupon_logo.png" alt="" title="Groupon Logo" width="176" height="74" class="alignright size-full wp-image-1608 right" /></a>
<p>
8th Light is one of a few companies that do work for Groupon, the local wunderkind. Our task was to write a small script to sync data between services for a small percentage of subscribers, but when a site has over <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5jaGFybGllcm9zZS5jb20vdmlldy9pbnRlcnZpZXcvMTEzMzg=">40 million</a> subscribers, you can&#8217;t just hack out something fast and hope for the best.
</p>

<p>
The work needed was very similar to an existing script, but Colin&#8217;s first instinct wasn&#8217;t a quick copy and paste and tweak. We analyzed the script to find the points of commonality and extracted them to a superclass, and we grew the existing tests (yes, the one-off script already had tests) to cover the new functionality.
</p>

<p>
I get the feeling that by the time I finish this tour I&#8217;m going to be pretty familiar with every combination of testing and mocking library out there. <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=LzIwMTAvY3JhZnRzbWFuc2hpcC10b3VyLW9idGl2YQ==">Last Monday</a> it was Cucumber, this time I dropped into learning rspec and its built-in mocking. I&#8217;m glad I <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvMjAwNy9zaW1wbGUtcnVieS1tb2NraW5n">experimented with writing my own mocking library</a> a few years ago, I earned a deeper understanding of mocking than one library&#8217;s API and was able to explain what I was trying to do and find the right bit of rspec docs quickly.
</p>

<p>
Every Friday lunch is &#8220;8th Light University&#8221; and a developer presents on an interesting topic. Colin gave a presentation on <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2Nsb2p1cmUub3Jn">Clojure</a>, walking through the basics of functional programming style like map, filter, and the importance of understanding when Clojure will or won&#8217;t walk an entire sequence to produce its result (as demonstrated by using <code>(range 10000000000000)</code>). It ended with a little exercise to add up all the numbers between 1 and 1000 that are evenly divisible by 3 and 5, my solution wasn&#8217;t too bad, though I should&#8217;ve used <code>reduce</code> in place of <code>filter/apply</code>:
</p>

<pre>
(defn evenly_divisible? [x] (or (= 0 (rem x 3)) (= 0 (rem x 5))))
(print (apply + (filter evenly_divisible? (drop 1 (range 1000)))))
</pre>

<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvd3AtY29udGVudC91cGxvYWRzLzIwMTAvMTIvbGltZWxpZ2h0LnBuZw=="><img src="http://push.cx/wp-content/uploads/2010/12/limelight.png" alt="" title="Limelight logo" width="169" height="44" class="alignright size-full wp-image-1609 right" /></a>
<p>
That refresher of Lisp syntax and FP came in handy immediately after lunch, when I paired with <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3R3aXR0ZXIuY29tL3NsYWd5cg==">Micah Martin</a>. He was working on adding a Clojure interface to the GUI toolkit <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2xpbWVsaWdodC44dGhsaWdodC5jb20vbWFpbi9kb3dubG9hZA==">Limelight</a>.
</p>

<p>
We refactored some Java and Clojure to remove some code duplicated logic for locating and loading GUI elements (&#8220;players&#8221;). I don&#8217;t really have any experience in Java, but it only took me about five minutes of removing duplication before I ran into hassles with the type system. 
</p>

<p>
As soon I was distracted by the interesting problem of structuring code in an unfamiliar language, my hands reverted to use <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3ZpbS5vcmc=">vim</a> commands. We were using <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5qZXRicmFpbnMuY29tL2lkZWEv">IntelliJ IDEA</a> on OS X, so I flailed a bit, at one point griping &#8220;I feel like I&#8217;m wearing mittens&#8221;. It&#8217;s disorienting to lose tools I&#8217;ve tweaked and practiced with almost daily for a dozen years.
</p>

<p>
The Java <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9naXRodWIuY29tL3NsYWd5ci9saW1lbGlnaHQvYmxvYi80YmY3MjljOTg3ZjFjNDE4YzVkNmE2NGJhNGYzNWZmZTNjNTJkMTk0L3NyYy9saW1lbGlnaHQvdWkvbW9kZWwvUGxheWVyUmVjcnVpdGVyLmphdmE=">started</a> like this:
</p>

<pre>&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #993333;">void</span> recruit<span style="color: #66cc66;">&#40;</span>PropPanel panel, <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5nb29nbGUuY29tL3NlYXJjaD9xPWFsbGludXJsJTNBU3RyaW5nK2phdmEuc3VuLmNvbSYjMDM4O2JudGw9MQ=="><span style="color: #aaaadd; font-weight: bold;">String</span></a> playerName, CastingDirector castingDirector<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">final</span> Scene scene = panel.<span style="color: #006600;">getRoot</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #000000; font-weight: bold;">final</span> <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5nb29nbGUuY29tL3NlYXJjaD9xPWFsbGludXJsJTNBU3RyaW5nK2phdmEuc3VuLmNvbSYjMDM4O2JudGw9MQ=="><span style="color: #aaaadd; font-weight: bold;">String</span></a> scenePlayersPath = scene.<span style="color: #006600;">getResourceLoader</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">pathTo</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">"players"</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #993333;">boolean</span> couldRecruitFromPScene = recruitFrom<span style="color: #66cc66;">&#40;</span>panel, playerName, castingDirector, scenePlayersPath<span style="color: #66cc66;">&#41;</span>;
  <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>!couldRecruitFromPScene<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">final</span> <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5nb29nbGUuY29tL3NlYXJjaD9xPWFsbGludXJsJTNBU3RyaW5nK2phdmEuc3VuLmNvbSYjMDM4O2JudGw9MQ=="><span style="color: #aaaadd; font-weight: bold;">String</span></a> productionPlayersPath = scene.<span style="color: #006600;">getProduction</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">getResourceLoader</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">pathTo</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">"players"</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #993333;">boolean</span> couldRecruitFromProduction = recruitFrom<span style="color: #66cc66;">&#40;</span>panel, playerName, castingDirector, productionPlayersPath<span style="color: #66cc66;">&#41;</span>;
    <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>!couldRecruitFromProduction<span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
      <span style="color: #993333;">boolean</span> couldRecruitDefaultPlayer = recruitFrom<span style="color: #66cc66;">&#40;</span>panel, playerName, builtinCastingDirector, BuiltinBeacon.<span style="color: #006600;">getBuiltinPlayersPath</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #66cc66;">&#125;</span>
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre>

<p>
I found this code really hard to read, in part because there were nested conditionals when it&#8217;s really doing the sequential work of trying different paths. It&#8217;s a bad application of <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2MyLmNvbS9jZ2kvd2lraT9TaW5nbGVGdW5jdGlvbkV4aXRQb2ludA==">single exit point</a> because Java is a garbage collected language. It&#8217;s OK to have multiple return points from a function because you don&#8217;t have to worry you&#8217;re leaking memory. So I <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9naXRodWIuY29tL3NsYWd5ci9saW1lbGlnaHQvYmxvYi82NmJlNTMzNWViYzUzNGNkYjEyNTM5ZWNjYTUwZTA2M2NmNWNjNzBkL3NyYy9saW1lbGlnaHQvdWkvbW9kZWwvUGxheWVyUmVjcnVpdGVyLmphdmE=">rewrote</a> it as:
</p>


<pre>&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #993333;">void</span> recruit<span style="color: #66cc66;">&#40;</span>PropPanel panel, <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5nb29nbGUuY29tL3NlYXJjaD9xPWFsbGludXJsJTNBU3RyaW5nK2phdmEuc3VuLmNvbSYjMDM4O2JudGw9MQ=="><span style="color: #aaaadd; font-weight: bold;">String</span></a> playerName, CastingDirector castingDirector<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">final</span> Scene scene = panel.<span style="color: #006600;">getRoot</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #000000; font-weight: bold;">final</span> <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5nb29nbGUuY29tL3NlYXJjaD9xPWFsbGludXJsJTNBU3RyaW5nK2phdmEuc3VuLmNvbSYjMDM4O2JudGw9MQ=="><span style="color: #aaaadd; font-weight: bold;">String</span></a> scenePlayersPath = scene.<span style="color: #006600;">getResourceLoader</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">pathTo</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">"players"</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #000000; font-weight: bold;">final</span> <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5nb29nbGUuY29tL3NlYXJjaD9xPWFsbGludXJsJTNBU3RyaW5nK2phdmEuc3VuLmNvbSYjMDM4O2JudGw9MQ=="><span style="color: #aaaadd; font-weight: bold;">String</span></a> productionPlayersPath = scene.<span style="color: #006600;">getProduction</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">getResourceLoader</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">pathTo</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">"players"</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>recruitFrom<span style="color: #66cc66;">&#40;</span>panel, playerName, castingDirector, scenePlayersPath<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">return</span>;
&nbsp;
  <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>recruitFrom<span style="color: #66cc66;">&#40;</span>panel, playerName, castingDirector, productionPlayersPath<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">return</span>;
&nbsp;
  recruitFrom<span style="color: #66cc66;">&#40;</span>panel, playerName, builtinCastingDirector, BuiltinBeacon.<span style="color: #006600;">getBuiltinPlayersPath</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre>

<p>
There are <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvMjAwNi9ydWJ5LWJsb2Nrcy1hbmQtYmxvY2tz">fewer variables</a> and I moved their initialization together, so your eye picks up the parallel structure and just focuses on the differences.
</p>

<p>
Of course, that&#8217;s not just parallel structure but repeated code in the conditionals and call to <code>recruitFrom()</code>. I fell into Ruby syntax trying to explain what I wanted to do as the next step of refactoring:
</p>

<pre>&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #993333;">void</span> recruit<span style="color: #66cc66;">&#40;</span>PropPanel panel, <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5nb29nbGUuY29tL3NlYXJjaD9xPWFsbGludXJsJTNBU3RyaW5nK2phdmEuc3VuLmNvbSYjMDM4O2JudGw9MQ=="><span style="color: #aaaadd; font-weight: bold;">String</span></a> playerName, CastingDirector castingDirector<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">final</span> Scene scene = panel.<span style="color: #006600;">getRoot</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#91;</span>
    <span style="color: #66cc66;">&#91;</span>scene.<span style="color: #006600;">getResourceLoader</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">pathTo</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">"players"</span><span style="color: #66cc66;">&#41;</span>,                 castingDirector<span style="color: #66cc66;">&#93;</span>,
    <span style="color: #66cc66;">&#91;</span>scene.<span style="color: #006600;">getProduction</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">getResourceLoader</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #006600;">pathTo</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">"players"</span><span style="color: #66cc66;">&#41;</span>, castingDirector<span style="color: #66cc66;">&#93;</span>,
    <span style="color: #66cc66;">&#91;</span>BuiltinBeacon.<span style="color: #006600;">getBuiltinPlayersPath</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>,                       builtinCastingDirector<span style="color: #66cc66;">&#93;</span>,
  <span style="color: #66cc66;">&#93;</span>.<span style="color: #006600;">each</span> <span style="color: #66cc66;">&#123;</span> |path, director|
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span>recruitFrom<span style="color: #66cc66;">&#40;</span>panel, playerName, director, path<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #000000; font-weight: bold;">return</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre>

<p>
Now the code doesn&#8217;t have any extra variables or repeated method calls. If the <code>recruitFrom</code> signature changed, there&#8217;d be exactly one place to change it.
</p>

<p>
Alas, it was not to be. I couldn&#8217;t simply bundle a <code>player</code> and a <code>canvas</code> in an array of tuples because they were of different types. Micah started typing a simple inner class to gather them together, but I vetoed it. Even though it would removtge duplication, I didn&#8217;t think it worth the tradeoff of added complexity of a new, data-only class. We left it at the previous revision.
</p>

<p>
Refactoring isn&#8217;t a blind set of tools to apply <code>while&nbsp;(code.has_refactoring_possible?)</code> because they&#8217;re about managing complexity by moving it to explicit places without duplication. You can spend hours smoothing things out only to be left with a stubborn bit of complexity that you can leave a warning on rather than spend a disproportionate amount of time trying to get that last bit. I find that when I do this, a future change will often expose what the real trouble is and I can advance the refactoring then.
</p>

<p>
All in all, a great day at 8th Light. I&#8217;m still looking for places to visit in Chicago before the end of the year, so please check out <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=L2NyYWZ0c21hbnNoaXAtY2FsZW5kYXI=">my calendar</a> and suggest places <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=L2NvbnRhY3Q=">here</a> or <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3R3aXR0ZXIuY29tL3B1c2hjeA==">on Twitter</a>.
</p>
 <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1601" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2010/craftsmanship-tour-8th-light/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Craftsmanship Tour: Obtiva</title>
		<link>http://push.cx/2010/craftsmanship-tour-obtiva</link>
		<comments>http://push.cx/2010/craftsmanship-tour-obtiva#comments</comments>
		<pubDate>Wed, 08 Dec 2010 03:03:52 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[craftsmanship]]></category>
		<category><![CDATA[craftsmanship tour]]></category>
		<category><![CDATA[Obtiva]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1520</guid>
		<description><![CDATA[Last month when I started planning my travels of indefinite duration, I ran into the blog On Being a Journeyman Software Developer by Corey Haines. He spent the end of 2008 and most of 2009 traveling around the United States pair programming in exchange for room and board, trading knowledge and having interesting discussions. I [...]]]></description>
			<content:encoded><![CDATA[<p>
Last month when I started planning my <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=L3RyYXZlbHMtb2YtaW5kZWZpbml0ZS1kdXJhdGlvbg==">travels of indefinite duration</a>, I ran into the blog <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3Byb2dyYW1taW5ndG91ci5ibG9nc3BvdC5jb20v">On Being a Journeyman Software Developer</a> by <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2NvcmV5aGFpbmVzLmNvbS8=">Corey Haines</a>.
He spent the end of 2008 and most of 2009 traveling around the United States pair programming in exchange for room and board, trading knowledge and having interesting discussions. I saw it and thought, &#8220;Hey, I could do that.&#8221;
</p>

<p>
I chatted with Corey about his experience and he encouraged me (and every other developer, really) to visit and learn from as many software developers as I could. To this end, he and Scott Parker introduced me to folks at Obtiva and 8th Light, two local consultancies that are part of the <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL21hbmlmZXN0by5zb2Z0d2FyZWNyYWZ0c21hbnNoaXAub3JnLw==">software craftsmanship</a> <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2dyb3Vwcy5nb29nbGUuY29tL2dyb3VwL3NvZnR3YXJlX2NyYWZ0c21hbnNoaXA=">movement</a>, with the encouragement that I visit places even before I leave Chicago.
</p>

<h2>Obtiva</h2>

<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL29idGl2YS5jb20="><img src="http://push.cx/wp-content/uploads/2010/12/obtiva.png" alt="" title="Obtiva logo" width="241" height="53" class="alignright size-full wp-image-1522 aside" /></a>
<p>
I&#8217;ve gotten my programming tour started. I spent yesterday at <a
href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL29idGl2YS5jb20=">Obtiva</a> pairing with <a
href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2FuZHltYWxlaC5ibG9nc3BvdC5jb20v">Andy Maleh</a> on some client work. We tracked down and fixed a bug, added a straightforward feature, and added a feature that exposed a hidden assumption in the spec and required some refactoring.
</p>

<p>
This was the first day I&#8217;ve spent pair programming and I really enjoyed the experience. There were some tools I hadn&#8217;t used, and Andy&#8217;s ability to answer a question, give an example, or push me to try it (&#8220;Here, you drive&#8221;) at the exact time I was wondering how to do something made for quick learning. We traded off responsibilities smoothly, with one of us writing the implementation and the other watching for typos and thinking of different possibilities. There were a few moments when I felt like I had a second brain because I had Andy&#8217;s knowledge to draw on or because he pointed out a problem I wouldn&#8217;t have noticed for a few minutes because I was heads-down on the current task.
</p>

<h2>Cucumber</h2>

<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2N1a2UuaW5mbw=="><img src="http://push.cx/wp-content/uploads/2010/12/cuke_logo.png" alt="" title="Cucumber logo" width="73" height="71" class="alignright size-full wp-image-1524 aside" /></a>
<p>
One of those new tools I saw was <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2N1a2VzLmluZm8v">Cucumber</a>, a test framework for <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9CZWhhdmlvcl9Ecml2ZW5fRGV2ZWxvcG1lbnQ=">behavior-driven development</a> and acceptance testing. You write your tests in lightly structured English and then write code to implement each step.
</p>

<p>
I&#8217;d seen a lot of talk around Cucumber but ignored it because I&#8217;m happy to write my high-level tests in Ruby. I don&#8217;t have a non-technical customer to show them to, so I didn&#8217;t see a benefit. I&#8217;m very glad to have gotten a little experience using Cucumber. It forces you to write a DSL for testing your app, with small, well-named methods to encapsulate each step of the process. It&#8217;s a great exercise that I&#8217;d recommend for anyone who writes automated tests (which is all developers, right? *cough*).
</p>

<h2>Dehumanize</h2>

<p>
As we were tidying up some Cucumber tests, I noticed a bit of repeated code that transformed an English description like &#8220;Phone number&#8221; into a column name like &#8220;phone_number&#8221;. We were about to abstract it to a small method, when Andy mentioned he&#8217;d submitted a small patch to Rails a while ago that was not accepted. Perhaps inspired by the <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3R3aXR0ZXIuY29tLyMhL2RlcmVrd2lsbGlzL3N0YXR1cy8xMDg2NDk3NTM3NTUwMzM2MA==">recent accomplishment</a> of a former coworker, I said, &#8220;Why don&#8217;t we package a gem?&#8221;
</p>

<p>
So that&#8217;s just what we did, creating the <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9naXRodWIuY29tL0FuZHlPYnRpdmEvZGVodW1hbml6ZQ==">dehumanize</a> gem for this snippet to perform the inverse of ActiveSupport::Inflectors#humanize. <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9naXRodWIuY29tL3RlY2huaWNhbHBpY2tsZXMvamV3ZWxlcg==">Jeweler</a> made it the work of a minute to package and publish; we spent more time retrieving Andy&#8217;s lost login to publish to <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3J1YnlnZW1zLm9yZy9nZW1zL2RlaHVtYW5pemU=">RubyGems</a>.
</p>

<p>
Aside from all these new toys, we had a nice running conversation on the size of commits and using feature branches. My tendency is to make much smaller and more frequent commits than Andy, and to break work off into branches much more often. Look for a blog post about it in the next few days.
</p>

<h2>Are you in Chicago?</h2>

<p>
If you&#8217;re in Chicago now and would like to spend a day pair programming with me, please <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=L2NvbnRhY3Q=">contact me</a>. There&#8217;s a lot to learn from each other, and it&#8217;s a lot of fun. At the least, you can follow <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=L2ZlZWQ=">this blog&#8217;s RSS feed</a> or <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3R3aXR0ZXIuY29tL3B1c2hjeA==">me on Twitter</a> to see how it goes.
</p> <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1520" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2010/craftsmanship-tour-obtiva/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Spreadsheet Errors</title>
		<link>http://push.cx/2010/spreadsheet-errors</link>
		<comments>http://push.cx/2010/spreadsheet-errors#comments</comments>
		<pubDate>Mon, 15 Nov 2010 02:25:51 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[bugs]]></category>
		<category><![CDATA[spreadsheets]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1487</guid>
		<description><![CDATA[Last week the magazine The Nation hurried to correct a story that they had suffered the worst drop in advertising of any weekly magazine. Their loss was actually in the middle of the pack, but the story was written from a spreadsheet that overstated their advertising for last year, giving them the appearance of a [...]]]></description>
			<content:encoded><![CDATA[<p>
Last week the magazine <i>The Nation</i> <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy50aGVuYXRpb24uY29tL2Jsb2cvMTU2MzgxL21hdGgtZXJyb3Itc2tld3MtbmF0aW9uLWFkLW51bWJlcnMtbW9uZGF5cy1uZXcteW9yay10aW1lcy1wcm9maWxl">hurried to correct</a> a story that they had suffered the worst drop in advertising of any weekly magazine. Their loss was actually in the middle of the pack, but the story was written from a spreadsheet that overstated their advertising for last year, giving them the appearance of a step decline.
</p>

<p>
Spreadsheets fascinate me. Lisp proponents point out that &#8220;code is data&#8221; but in a spreadsheets data is code. Formulas inhabit the cells of the data they represent, a much closer pairing than code files on the same drive as data files.
</p>

<p>
Spreadsheets are used in institutions of every size, from businesses to government agencies and all the individuals along he way. They were the first <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9LaWxsZXJfYXBw">killer app</a> and are nearly as ubiquitous as desktop computing. I suspect that most small businesses would be out of business in weeks if they lost the key spreadsheets that get forwarded between office workers and, perhaps, only one employee is allowed to update a master copy of. (This is part of why I&#8217;m not surprised that <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5kcm9wYm94LmNvbQ==">DropBox</a> is doing very well.)
</p>

<p>
Errors are endemic. I found a nice <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3BhbmtvLnNoaWRsZXIuaGF3YWlpLmVkdS9zc3IvTXlwYXBlcnMvd2hhdGtub3cuaHRt">roundup of research</a> into spreadsheet errors and, even in constrained experimental conditions the cell error rate is above 1%. In a spreadsheet with 100 cells of data, there&#8217;s probably at least one error; if there are formulas the rate jumps to 5-15%.
</p>

<p>
Sometimes this disturbs me, to think of how many errors are creeping along in everything I rely on. How many numbers could I type before I transposed two digits without knowing? Formulas are small, untested programs written in a haphazardly designed language by people who have not studied programming. The design of the software makes mistakes as trivial (for example, click a formula term, change your mind, hit the arrow keys, and you&#8217;ve changed the cell the formula is reading data from). It&#8217;s astonishing that so many institutions rely on something so unreliable.
</p>

<p>
But on reflection I think it&#8217;s a sign that institutions are more robust than they might appear to first glance. The lights are still on, police still go to the right neighborhoods, products arrive for store shelves. I&#8217;ve seen a few attempts to make more rigorous spreadsheets, with data typing, validity checks, embedded programming languages. But I don&#8217;t see people lining up to pay that overhead, the benefits they would bring aren&#8217;t worthwhile, or at least the losses they would avert are not conspicuously attributable to the lack of those controls.
</p>

<p class="aside">
Thanks for <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3R3aXR0ZXIuY29tL01hY0RpdmFPTkE=">Chrys Wu</a> for the <i>Nation</i> story.
</p> <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1487" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2010/spreadsheet-errors/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reading 400 Feeds with Newsbeuter</title>
		<link>http://push.cx/2010/reading-400-feeds-with-newsbeuter</link>
		<comments>http://push.cx/2010/reading-400-feeds-with-newsbeuter#comments</comments>
		<pubDate>Tue, 07 Sep 2010 15:29:58 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[feeds]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1441</guid>
		<description><![CDATA[I posted a few years ago about looking for a good Linux feed reader and a reader&#8217;s email reminded me to revisit the topic. It&#8217;s time for another blog post where I talk about how I overthink some part of my daily routine but it lets me do in a few minutes what I could [...]]]></description>
			<content:encoded><![CDATA[<p>
I posted a few years ago about <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvMjAwNi9rbm93LWEtZ29vZC1saW51eC1mZWVkLXJlYWRlcg==">looking for a good Linux feed reader</a> and a reader&#8217;s email reminded me to revisit the topic. It&#8217;s time for another blog post where I talk about how I overthink some part of my daily routine but it lets me do in a few minutes what I could otherwise waste a few hours on.
</p>

<blockquote>
Could anyone recommend a good feed reader for Linux? I need to be able to organize my ~160 feeds in folders, read an entire feed or set of feeds without having to click incessantly, and get already-read items out of the way. 
</blockquote>

<p>
Since I wrote that, tagging has replaced folders, I have over 400 feeds, and I&#8217;ve adopted <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL25ld3NiZXV0ZXIub3Jn">Newsbeuter</a> for reading my feeds. It&#8217;s a great console-based feed reader that lets me zip through my feeds with vim-like keybindings. I&#8217;ve included my config file at the bottom of this post.
</p>

<p>
I&#8217;ve found it most useful to tag my feeds by how often they update. I&#8217;ve found five broad categories:
</p>

<dl>
  <dt>Personal</dt><dd>Feeds related to my projects and the blogs of friends and family. I want to read all of these several times per day.</dd>
  <dt>Daily</dt><dd>Mostly comics and commentators that update 3-7 times per week, but usually only once per day. These are time-insensitive entertainment, so I can let them build up for a few days or weeks before I go through them.</dd>
  <dt>Irregular</dt><dd>This is the vast bulk of my feeds and update between once per week and once per year. When I like a blog and enjoy reading its archive, I&#8217;ll follow it to keep an eye out for new posts. I could read this as infrequently as every month.</dd>
  <dt>Noisy</dt><dd>I only follow a handful of blogs that update multiple times per day and I&#8217;ll read them every day or few days, skimming most of the items. Usually any blog that updates this frequently has a pretty lousy signal-to-noise ratio, so they don&#8217;t tend to stay in my feedlist for more than a month or two at a time before I get fed up.</dd>
  <dt>Aggregators</dt><dd>Social news sites, usually I read them once in the morning and once in the evening. Sometimes more often if I&#8217;m procrastinating.</dd>
</dl>

<p>
I&#8217;ve found it far more useful to tag my feeds by these reading habits than by their topic. I can sit down to read whatever my current time and attention allow rather than wading through all of it at once.
</p>

<p>
There&#8217;s only one feature I&#8217;d like from Newsbeuter. When I travel, I may be offline for several days and only have a few minutes of connectivity when I do get on. I&#8217;d like to leave a script of some kind running on a shell account somewhere to collect feed items to quickly spool to me when I&#8217;m online. Alternately, I&#8217;d be happy running newsbeuter on a remote host if I could still open tabs in my local browser as usual.
</p>

<p>
Here&#8217;s that config file:
</p>

<code><pre>
# no automatic reloading
refresh-on-startup no
auto-reload no
reload-time 360 # minutes

# reloading
reload-threads 4
reload-only-visible-feeds no
show-read-feeds no
download-retries 4

# notification
notify-screen yes
notify-xterm yes

# storage
max-items 200

# external programs - ff is a firefox wrapper
browser ff

# display
article-sort-order date-desc
feedlist-format "%S%n %11u %t"
articlelist-format "%D %f %?T?;%-17T; ?%t"
datetime-format %m-%d
color background white black
color listnormal white black
color listfocus black white
color info black white
color article white black

# interface
confirm-exit yes
bind-key k up
bind-key j down
bind-key O open-in-browser-and-mark-read
</pre></code> <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1441" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2010/reading-400-feeds-with-newsbeuter/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Globalton</title>
		<link>http://push.cx/2010/globalton</link>
		<comments>http://push.cx/2010/globalton#comments</comments>
		<pubDate>Thu, 26 Aug 2010 12:50:51 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[design patterns]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1438</guid>
		<description><![CDATA[It&#8217;s Steve Yegge&#8217;s fault that I was rethinking the singleton pattern. I read his Singleton Considered Stupid post in early 2008 with the rest of the proggit before it devolved into a memetic garbage patch. Yegge&#8217;s rant ends with a note about design patterns that curled up in my hindbrain and has been whispering to [...]]]></description>
			<content:encoded><![CDATA[<p>
It&#8217;s Steve Yegge&#8217;s fault that I was rethinking the singleton pattern. I read his <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3NpdGVzLmdvb2dsZS5jb20vc2l0ZS9zdGV2ZXllZ2dlMi9zaW5nbGV0b24tY29uc2lkZXJlZC1zdHVwaWQ=">Singleton Considered Stupid</a> post in early 2008 with the rest of the <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5yZWRkaXQuY29tL3IvcHJvZ3JhbW1pbmcv">proggit</a> before it devolved into a memetic <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9HcmVhdF9QYWNpZmljX0dhcmJhZ2VfUGF0Y2g=">garbage patch</a>. Yegge&#8217;s rant ends with a note about design patterns that curled up in my hindbrain and has been whispering to me since:
</p>

<blockquote>
The problem is, about 1/3 to 1/2 of them [design patterns] were basically cover-ups for deficiencies in C++ that don&#8217;t exist in other languages. Although I&#8217;m not a huge Perl fan anymore, I have to admit the Perl community caught on to this first (or at least funniest). They pointed out that many of these so-called patterns were actually an implementation of Functional Programming in C++. 
</blockquote>

<p>
I&#8217;ve had the <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2NvbW11bml0eS5iYmdhbWV6b25lLm5ldC9pbmRleC5waHAvdG9waWMsMjgyMC5tc2cxOTk4OC5odG1s">ranty discussions</a> about how the singleton could be better known as <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3R3aXR0ZXIuY29tL0tlbnRCZWNrL3N0YXR1cy8xMjI4MzY5NjI5Mg==">globalton</a> typical of any developer who&#8217;s heard that joke:
</p>

<blockquote>
I&#8217;ve never understood why people bother with all that mucking around with instances. Just tag the object initialization on to the end some startup script like the database initialization and add &#8216;global $map;&#8217; anytime you want to access it. It&#8217;s a global variable; most languages have very succinct idioms for managing those, unfortunately.
</blockquote>

<p>
Singleton has a very small niche managing some hardware access and then is abused approximately all of the time as a noisy version of global variables. Seeing this over and over kept me thinking about whether design patterns are indeed mostly a standard set of tools for working around language deficiencies. (ObSlander: It&#8217;d certainly explain the Java community&#8217;s fixation on them.)
</p>

<p>
I&#8217;ve had an urge to reread <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2RwLzAyMDE2MzM2MTIvP3RhZz1wdXNoY3gtMjA=">Design Patterns</a> and work through them in a high-level language like <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2Rlc2lnbnBhdHRlcm5zaW5ydWJ5LmNvbS9zZWN0aW9uMDEvYXJ0aWNsZS5odG1s">Ruby</a> or, better, JavaScript.
</p>

<p>
But it turns out, as usual, that Peter Norvig is way ahead, with a <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL25vcnZpZy5jb20vZGVzaWduLXBhdHRlcm5zLw==">1998 presentation</a> on design patterns in dynamic language noting that in some languages design patterns are simply invisible. Unfortunately he didn&#8217;t leave behind a detailed pronouncement of opinion as to the value remaining in design patterns when a language invisibly supports the most common patterns at the least, so I suppose I still have the exercise ahead of me.
</p> <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1438" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2010/globalton/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>From Fixtures to Factories</title>
		<link>http://push.cx/2010/from-fixtures-to-factories</link>
		<comments>http://push.cx/2010/from-fixtures-to-factories#comments</comments>
		<pubDate>Tue, 06 Jul 2010 19:33:02 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[factories]]></category>
		<category><![CDATA[factory_girl]]></category>
		<category><![CDATA[fixtures]]></category>
		<category><![CDATA[Mocha]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1428</guid>
		<description><![CDATA[Automated tests need example data, and it&#8217;s a pain to have to construct a complete object in every test, especially when there are a lot of non-optional fields. The standard improvement is to use fixtures, a file with some example data, that your tests can load by giving the name of a fixture. Here&#8217;s one [...]]]></description>
			<content:encoded><![CDATA[<p>
<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=L3RhZy90ZXN0aW5n">Automated tests</a> need example data, and it&#8217;s a pain to have to construct a complete object in every test, especially when there are a lot of non-optional fields.
</p>

<p>
The standard improvement is to use fixtures, a file with some example data,
that your tests can load by giving the name of a fixture. Here&#8217;s one of the
fixtures for a <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL05lYXJieUdhbWVycy5jb20=">gamer</a>:
</p>

<pre>
alice: # alice is heavily involved
  id: 1
  mail: alice@example.com
  handle: alice
  password: red queen
  teaser: Follow the white rabbit.
  profile: Not so plain, after all.
  homepage: http://www.example.com
  jabber: alice@example.org
  location_id: 3
  last_login: 2006-10-30 11:56:08
  created_at: 2006-10-30 11:56:08
  location_at: 2006-10-30 11:56:08
  tag_text: dnd, wod
  mail_on_message: true
  mail_on_nearby_discussion: true
</pre>

<p>
This is straightforward, but <kbd>location_id</kbd> is the id of another fixture in another file. As you can imagine it&#8217;s pretty easy to get them out-of-sync and break some tests. I end up leaving little <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2MyLmNvbS9jZ2kvd2lraT9Ub05lZWRDb21tZW50cw==">comments</a> in the YAML to remind myself of the cross-reference.
</p>

<p>
It&#8217;s awfully tempting to reuse fixtures from test to test. Maybe Alice was written to test logging in with a username and password and next I&#8217;m writing the test of logging in with an email address and a password. I could copy and paste Alice to another fixture to reuse in that test, but as a programmer I have a pathological aversion to copy and paste. Alice is going to get reused (most of those fields are optional and were used by very different tests), and after this happens a few times it&#8217;s hard to change a fixture without breaking an unrelated test.
</p>

<p>
I&#8217;ve gotten a lot of use out of fixtures as I&#8217;ve developed the habit of <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvMjAwOS93aHktaS13cml0ZS10ZXN0cw==">testing all my code</a>, but reuse has made my tests somewhat brittle. After a bit of research, I&#8217;ve moved over to using factories.
</p>

<p>
Here&#8217;s the factory for a gamer:
</p>

<pre>&nbsp;
Factory.<span style="">sequence</span> :handle <span style="color: #66cc66;">&#123;</span> |n| <span style="color: #ff0000;">"Gamer_#{n}"</span> <span style="color: #66cc66;">&#125;</span>
&nbsp;
Factory.<span style="">define</span> :gamer <span style="color: #b1b100;">do</span> |g|
  g.<span style="">handle</span> <span style="color: #66cc66;">&#123;</span> Factory.<span style="">next</span> :handle <span style="color: #66cc66;">&#125;</span>
  g.<span style="">mail</span> <span style="color: #66cc66;">&#123;</span> |m| <span style="color: #ff0000;">"#{m.handle}@example.com"</span> <span style="color: #66cc66;">&#125;</span>
  g.<span style="">password</span> <span style="color: #ff0000;">'secret'</span>
<span style="color: #b1b100;">end</span></pre>

<p>
Only the essential, required fields are listed. Using this simple template, the tests themselves specify the values of the fields they&#8217;ll be testing.
</p>

<pre>&nbsp;
def test_login_with_valid_username_and_password
  gamer = Gamer.<span style="">create</span> :handle =&gt; <span style="color: #ff0000;">'Alice'</span>, :password =&gt; <span style="color: #ff0000;">'red queen'</span>
  ...
<span style="color: #b1b100;">end</span>
def test_login_with_valid_email_and_password
  gamer = Gamer.<span style="">create</span> :mail =&gt; <span style="color: #ff0000;">'alice@example.com'</span>, :password =&gt; <span style="color: #ff0000;">'red queen'</span>
  ...
<span style="color: #b1b100;">end</span></pre>

<p>
Ideally, changing a fixture wouldn&#8217;t break any tests at all. And <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2dpdGh1Yi5jb20vdGhvdWdodGJvdC9mYWN0b3J5X2dpcmw=">factory_girl</a> (what I&#8217;m using for factories in Rails) makes associations easy:
</p>

<pre>&nbsp;
Factory.<span style="">define</span> :post <span style="color: #b1b100;">do</span> |p|
  p.<span style="">association</span> :discussion, :factory =&gt; :discussion
  p.<span style="">association</span> :poster, :factory =&gt; :gamer
  p.<span style="">created_at</span> Time.<span style="">now</span>.<span style="">utc</span>
  p.<span style="">body</span> <span style="color: #ff0000;">"Post Body"</span>
<span style="color: #b1b100;">end</span></pre>

<p>
Now my tests include the specific data they care about, making them easier to understand and improve. And they don&#8217;t interrelate, so they&#8217;re much more reliable. I do still use fixtures, but now they&#8217;re exclusively for tests that need to deal with real-world examples.
</p>
 <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1428" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2010/from-fixtures-to-factories/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>PHP Hex Map Graphics</title>
		<link>http://push.cx/2010/php-hex-map-graphics</link>
		<comments>http://push.cx/2010/php-hex-map-graphics#comments</comments>
		<pubDate>Sun, 13 Jun 2010 02:24:46 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[hex maps]]></category>
		<category><![CDATA[image generation]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[web games]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1392</guid>
		<description><![CDATA[This PHP code uses the GD functions to create hex map images (eg. for wargames). Leland on GitHub Features: Shapes: rectangule, hexagonal (&#8216;circle&#8217;), freeform (&#8216;free&#8217;) Variable hex sizes shape() to calculate distance in hexes highlight a hex set a border on a hex color a hex add text to a hex I swear it used [...]]]></description>
			<content:encoded><![CDATA[<p>
This PHP code uses the GD functions to create hex map images (eg. for wargames).
</p>

<p><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2dpdGh1Yi5jb20vcHVzaGN4L2xlbGFuZA==">Leland on GitHub</a></p>

<h2>Features:</h2>

<ul>
  <li>Shapes: rectangule, hexagonal (&#8216;circle&#8217;), freeform (&#8216;free&#8217;)</li>
  <li>Variable hex sizes</li>
  <li>shape() to calculate distance in hexes</li>
  <li>highlight a hex</li>
  <li>set a border on a hex</li>
  <li>color a hex</li>
  <li>add text to a hex</li>
  <li>I swear it used to allow setting a background picture, but I don&#8217;t see that functionality so maybe I dreamed it or lost it when I misplaced this code for four years.</li>
</ul>

<h2>Known Issues</h2>

<p>
The code has ugly styling (tabs, odd spacing, no optional braces) &#8211; sorry, I was young(er) and stupid(er).
</p>

<p>
There&#8217;s a fair amount of temporal coupling in there &#8211; functions that you can&#8217;t call before other functions, etc. I hadn&#8217;t heard of the command pattern or closures yet.
</p>

<img src="http://push.cx/wp-content/uploads/2010/06/hex_map_test.png" alt="" title="Hex map test" width="191" height="161" class="alignnone size-full wp-image-1395 content" />

<p>
There&#8217;s a bug in the &#8216;circle&#8217; shape (that the following code exercises):
</p>

<pre>&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
&nbsp;
<span style="color: #b1b100;">require</span> <span style="color: #ff0000;">'class_hex_image.php'</span>;
&nbsp;
<span style="color: #0000ff;">$radius</span> = <span style="color: #cc66cc;">3</span>;
<span style="color: #0000ff;">$map</span> = <span style="color: #000000; font-weight: bold;">new</span> Hex_image;
<span style="color: #0000ff;">$map</span>-&gt;<span style="color: #006600;">set_color</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'bg'</span>, <span style="color: #cc66cc;">255</span>, <span style="color: #cc66cc;">255</span>, <span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$map</span>-&gt;<span style="color: #006600;">set_l</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$map</span>-&gt;<span style="color: #006600;">set_shape</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'circle'</span>, <span style="color: #0000ff;">$radius</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$map</span>-&gt;<span style="color: #006600;">start</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$x</span> = <span style="color: #cc66cc;">1</span>; <span style="color: #0000ff;">$x</span> &lt;= <span style="color: #0000ff;">$map</span>-&gt;<span style="color: #006600;">xsize</span>; <span style="color: #0000ff;">$x</span>++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$y</span> = <span style="color: #cc66cc;">1</span>; <span style="color: #0000ff;">$y</span> &lt;= <span style="color: #0000ff;">$map</span>-&gt;<span style="color: #006600;">ysize</span>; <span style="color: #0000ff;">$y</span>++<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
        <span style="color: #0000ff;">$map</span>-&gt;<span style="color: #006600;">text</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$x</span>, <span style="color: #0000ff;">$y</span>, <span style="color: #ff0000;">'black'</span>, <span style="color: #0000ff;">$map</span>-&gt;<span style="color: #006600;">steps</span><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$x</span>, <span style="color: #0000ff;">$y</span>, <span style="color: #0000ff;">$radius</span>, <span style="color: #0000ff;">$radius</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
        <span style="color: #808080; font-style: italic;">// nice for getting a feel for coordinates</span>
        <span style="color: #808080; font-style: italic;">//$map-&gt;text($x, $y, 'black', &quot;$x,$y&quot;);</span>
    <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5waHAubmV0L2hlYWRlcg=="><span style="color: #000066;">header</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'Content-Type: image.png'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #0000ff;">$map</span>-&gt;<span style="color: #006600;">finish</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;       <span style="color: #808080; font-style: italic;">// calls imagepng()</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre>

<h2>Future</h2>

<p>
One of the guys in #bbg on irc,freenode.net is building a browser-based game with a hex map and I remembered this code was squirreled away somewhere on my hard drive. I have no plans to fix, improve, or in any way maintain this code. I figure I may as well release it so someone can do something with it.
</p>

<h2>License</h2>

<p>
I release this code to the public domain. You may use it for any purpose with or without attribution. It would be polite to mention my name and let me know you come up with, but it&#8217;s not at all required.
</p>
 <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1392" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2010/php-hex-map-graphics/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Hackers and Gamers</title>
		<link>http://push.cx/2010/hackers-and-gamers</link>
		<comments>http://push.cx/2010/hackers-and-gamers#comments</comments>
		<pubDate>Wed, 05 May 2010 14:36:22 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1367</guid>
		<description><![CDATA[I&#8217;ve been meaning to mention for a while that I&#8217;ve been contributing to the tumblelog Hackers and Gamers to share interesting links at the intersection of business, code, and gaming. The blog was started by Peter Christensen and has one or two other contributors. With two Peters involved, here&#8217;s the handy guide to tell us [...]]]></description>
			<content:encoded><![CDATA[<p>
I&#8217;ve been meaning to mention for a while that I&#8217;ve been contributing to the tumblelog <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2hhY2tlcnNhbmRnYW1lcnMucG9zdGVyb3VzLmNvbQ==">Hackers and Gamers</a> to share interesting links at the intersection of business, code, and gaming.
</p>

<p>
The blog was started by <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5wY2hyaXN0ZW5zZW4uY29tL2Jsb2cv">Peter Christensen</a> and has one or two other contributors. With two Peters involved, here&#8217;s the handy guide to tell us apart: <i>He&#8217;s</i> the guy in Chicago named Peter who&#8217;s building a startup around an unconventional web-based game and <i>I&#8217;m</i> the guy in Chicago named Peter who&#8217;s building a startup around an unconventional web-based game.
</p> <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1367" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2010/hackers-and-gamers/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>One Fine Git Book: Pro Git</title>
		<link>http://push.cx/2010/one-fine-git-book-pro-git</link>
		<comments>http://push.cx/2010/one-fine-git-book-pro-git#comments</comments>
		<pubDate>Sat, 24 Apr 2010 16:07:06 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[book review]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[version control]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1316</guid>
		<description><![CDATA[As long as I&#8217;m reading too much, let me suggest that you can skip the couple dozen blog posts and half-dozen books about Git. Read this one introductory blog post and, if git sounds like a good tool for you, you can read one fine book about Git and be thoroughly informed. I was reading [...]]]></description>
			<content:encoded><![CDATA[<p>
As long as I&#8217;m <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=LzIwMTAvYWRtaXR0aW5nLWRpbWluaXNoaW5nLXJldHVybnM=">reading too much</a>, let me suggest that you can skip the couple dozen blog posts and half-dozen books about Git. Read this one introductory blog post and, if git sounds like a good tool for you, you can read one fine book about Git and be thoroughly informed.
</p>

<p>
I was reading through <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3RvbS5wcmVzdG9uLXdlcm5lci5jb20v">the blog</a> of one of the <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2dpdGh1Yi5jb20=">GitHub</a> cofounders and an article caught my eye because it described a process very similar to the one that I&#8217;ve heard from people who don&#8217;t use any version control:
</p>

<blockquote>
You start your project in a directory named working. As you code, you try to write one feature at a time. When you complete a self-contained portion of a feature, you make sure that all your files are saved and then make a copy of the entire working directory, giving it the name snapshot-0. After you perform this copy operation, you make sure to never again change the code files in the new directory. After the next chunk of work, you perform another copy, only this time the new directory gets the name snapshot-1, and so on.
</blockquote>

<p>
I like this because doesn&#8217;t insult anyone for using a process like this (as I&#8217;m occasionally tempted to do). Instead, he sees it as the first step toward the design of a distributed version control system (DVCS) to manage the process. He explains how a version control system encapsulates all the best practices people have learned from decades of coding and collaborating into a reliable software tool.
</p>

<blockquote>
The following parable will take you on a journey through the creation of a Git-like system from the ground up. Understanding the concepts presented here will be the most valuable thing you can do to prepare yourself to harness the full power of Git. The concepts themselves are quite simple, but allow for an amazing wealth of functionality to spring into existence. Read this parable all the way through and you should have very little trouble mastering the various Git commands and wielding the awesome power that Git makes available to you.
</blockquote>

<p>
For anybody still on the fence about whether version control is worthwhile, give <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3RvbS5wcmVzdG9uLXdlcm5lci5jb20vMjAwOS8wNS8xOS90aGUtZ2l0LXBhcmFibGUuaHRtbA==">The Git Parable</a> a read to find out why most developers consider it a necessity. And even if you&#8217;re already familiar with version control it&#8217;s worth a read to get the basic concepts behind git (like that a commit it not a changeset, as in svn).
</p>

<p>
If it gets you curious to learn git, the free book <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3Byb2dpdC5vcmcvYm9vaw==">Pro Git</a> is the one book you should read. It combines straightforward, readable prose with clear diagrams:
</p>

<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvd3AtY29udGVudC91cGxvYWRzLzIwMTAvMDQvZmlsZV9zdGF0dXNfbGlmZWN5Y2xlLnBuZw=="><img src="http://push.cx/wp-content/uploads/2010/04/file_status_lifecycle-300x190.png" alt="" title="File status lifecycle" width="300" height="190" style="float: left" /></a>
<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvd3AtY29udGVudC91cGxvYWRzLzIwMTAvMDQvbWVyZ2UucG5n"><img src="http://push.cx/wp-content/uploads/2010/04/merge-300x159.png" alt="" title="Merge structure" width="300" height="159" style="float: left" /></a>
<hr class="clear">

<blockquote>
<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2RwLzE0MzAyMTgzMzkvP3RhZz1wdXNoY3gtMjA="><img src="http://push.cx/wp-content/uploads/2010/04/pro_git.jpg" alt="" title="Pro Git Cover" width="115" height="115" class="decoration" /></a>Because Git uses a simple three-way merge, merging from one branch into another multiple times over a long period is generally easy to do. This means you can have several branches that are always open and that you use for different stages of your development cycle; you can merge regularly from some of them into others.

Many Git developers have a workflow that embraces this approach, such as having only code that is entirely stable in their master branch — possibly only code that has been or will be released. They have another parallel branch named develop or next that they work from or use to test stability — it isn’t necessarily always stable, but whenever it gets to a stable state, it can be merged into master. It’s used to pull in topic branches (short-lived branches, like your earlier iss53 branch) when they’re ready, to make sure they pass all the tests and don’t introduce bugs.
</blockquote>

<p>
This book is the best because Chacon finds the right balance between day-to-day interaction examples and exposing the underlying data model. It finds the right balance between &#8220;Don&#8217;t worry about this magic here&#8221; and &#8220;and now a discourse on directed acyclic graphs&#8221;.
</p>

<p>
And once you&#8217;ve read it, stop. You <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=LzIwMTAvYWRtaXR0aW5nLWRpbWluaXNoaW5nLXJldHVybnM=">don&#8217;t need to read anything more</a> about git, go forth and code.
</p>

<h2>Also Considered</h2>

<p>
The most common negative here is that a work is out of date: Git went from having almost nothing besides man pages from 2005-2007 to an explosion of introductory stuff in 2008 and early 2009. There were also a few significant UI improvements to git in late 2008 and through 2009 &mdash; so anything from before then will have a few confusing odds and ends, which is a problem when learning a system that&#8217;s already somewhat complex and opaque.
</p>

<dl>
  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2Jvb2suZ2l0LXNjbS5jb20v">Git Community Book</a></dt>
  <dd>A close second, the Git Community Book is only slightly less well-structured.</dd>

  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2RwLzA1OTY1MjAxMjMvP3RhZz1wdXNoY3gtMjA=">Version Control With Git</a></dt>
  <dd>A little disorganized (there&#8217;s a lot of &#8220;X will be explained a few chapters from now&#8221;), but the O&#8217;Reilly house style you know well.</dd>

  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5rZXJuZWwub3JnL3B1Yi9zb2Z0d2FyZS9zY20vZ2l0L2RvY3MvdXNlci1tYW51YWwuaHRtbA==">Git user Manual</a></dt>
  <dd>Comprehensive and official, but no handholding, this is largely composed of man pages (<a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2RwLzAzODA4MTU5MzEvP3RhZz1wdXNoY3gtMjA=">&#8230;</a>&#8220;which read like the terse mutterings of pilots wrestling with the controls of damaged airplanes&#8221;).</dd>

  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5hbWF6b24uY29tL2RwLzE5MzQzNTYxNTgvP3RhZz1wdXNoY3gtMjA=">Pragmatic Version Control Using Git</a></dt>
  <dd>Well-written and includes a nice reference to git-svn. There&#8217;s nothing wrong with this book, but Pro Git is newer and has great diagrams.</dd>

  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2xlYXJuLmdpdGh1Yi5jb20v">Learn Git</a></dt>
  <dd>Well-written (it&#8217;s also largely by the indefatigable Chacon) but incomplete.</dd>

  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cHM6Ly9wZWVwY29kZS5jb20vcHJvZHVjdHMvZ2l0LWludGVybmFscy1wZGY=">Git Internals</a></dt>
  <dd>Scott Chacon&#8217;s first excellent introduction, great but less complete than Pro Git. I haven&#8217;t seen the <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3BlZXBjb2RlLmNvbS9wcm9kdWN0cy9naXQ=">screencast</a>.</dd>

  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy1jcy1zdHVkZW50cy5zdGFuZm9yZC5lZHUvfmJseW5uL2dpdG1hZ2ljLw==">Git Magic</a></dt>
  <dd>Fairly comprehensive, but it feels a bit too conversational and doesn&#8217;t explain behind-the-scenes fundamentals.</dd>

  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2VhZ2Fpbi5uZXQvYXJ0aWNsZXMvZ2l0LWZvci1jb21wdXRlci1zY2llbnRpc3RzLw==">Git for Computer Scientists</a></dt>
  <dd>&#8220;And now a discourse on directed acyclic graphs.&#8221; A short article on git&#8217;s data structures.</dd>

  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5naXRyZWFkeS5jb20v">Git Ready</a></dt>
  <dd>A friendly blog with bite-sized topics, appears defunct.</dd>

  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3ZpZGVvLmdvb2dsZS5jb20vdmlkZW9wbGF5P2RvY2lkPS0zOTk5OTUyOTQ0NjE5MjQ1Nzgw">Randal Schwartz on Git</a></dt>
  <dd>For too long this was the only beginner intro to git; by the Hooter&#8217;s guy.</dd>

  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy55b3V0dWJlLmNvbS93YXRjaD92PTRYcG5LSEpBb2s4">Linus Torvalds on Git</a></dt>
  <dd>A fun hour of Torvalds being rude and occasionally awesome, but not any real introduction.</dd>

  <dt>Using Git Without Feeling Stupid <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3NtYWxsdGFsay5nbnUub3JnL2Jsb2cvYm9uemluaXAvdXNpbmctZ2l0LXdpdGhvdXQtZmVlbGluZy1zdHVwaWQtcGFydC0x">One</a> <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3NtYWxsdGFsay5nbnUub3JnL2Jsb2cvYm9uemluaXAvdXNpbmctZ2l0LXdpdGhvdXQtZmVlbGluZy1zdHVwaWQtcGFydC0y">Two</a></dt>
  <dd>Brief pair of blog posts giving a basic introduction</dd>

  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy52aW1lby5jb20vMzY5MDk1">Git with Rails Tutorial</a></dt>
  <dd>Outdated and only about deployment.</dd>

  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5lZWNzLmhhcnZhcmQuZWR1L35jZHVhbi90ZWNobmljYWwvZ2l0Lw==">Understanding Git Conceptually</a></dt>
  <dd>Basic info on branching, merging, remote repositories, but that&#8217;s all.</dd>

  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2dpdGNhc3RzLmNvbS8=">GitCasts</a></dt>
  <dd>An outdated and defunct screencast blog.</dd>

  <dt><a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2V4Y2Vzcy5vcmcvYXJ0aWNsZS8yMDA4LzA3L29ncmUtZ2l0LXR1dG9yaWFsLw==">Git the basics</a></dt>
  <dd>A good 130m talk on git, but it&#8217;s all the data structures before the hands-on.</dd>

</dl>

<p>&#8230;and a few dozen other brief blog posts and talks that aren&#8217;t worth linking to.</p>
 <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1316" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2010/one-fine-git-book-pro-git/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>HTML is Your Markup Language Anyways</title>
		<link>http://push.cx/2009/html-is-your-markup-language-anyways</link>
		<comments>http://push.cx/2009/html-is-your-markup-language-anyways#comments</comments>
		<pubDate>Tue, 10 Nov 2009 21:53:24 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[bbcode]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[markdown]]></category>
		<category><![CDATA[markup languages]]></category>

		<guid isPermaLink="false">http://push.cx/?p=297</guid>
		<description><![CDATA[I hate Wiki markup. I hate BBCode. I hate markdown. I hate the million other custom markup languages that have infested the web. When you&#8217;re using one of these markup languages, you&#8217;re using HTML anyways. Because they must be translated to HTML to serve as web pages, at best they&#8217;re poor translations of HTML. A [...]]]></description>
			<content:encoded><![CDATA[<p>
I hate Wiki markup. I hate BBCode. I hate markdown. I hate the million other custom markup languages that have infested the web.
</p>

<p>
When you&#8217;re using one of these markup languages, you&#8217;re using HTML anyways. Because they must be translated to HTML to serve as web pages, at best they&#8217;re poor translations of HTML. A lot of them are &#8220;parsed&#8221; with regular expressions, leading to all kinds of interesting bugs with nested tags. MediaWiki (the engine behind Wikipedia) uses two apostrophes for &#8221;<b>bold</b>&#8221; and three for &#8221;&#8217;<i>italic</i>&#8221;&#8217;, and then just lets you use HTML for all the cases where these things break. Most markup languages have some passthrough like this to deal with ambiguity or complexity &#8212; so while some markups (not BBCode, which is like HTML in brackets) can claim to be easier to start using, users always end up learning HTML in the end.
</p>

<p>
MediaWiki actually has a decent argument for custom markup in its ability to build <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3d3dy5tZWRpYXdpa2kub3JnL3dpa2kvSGVscDpUZW1wbGF0ZQ==">templates</a> and fill in particular fields with data. These custom tags aren&#8217;t available in HTML, but there&#8217;s nothing stopping a site from adding its own tags (which may or may not look much like HTML) that are compiled down to HTML in the exact same fashion.
</p>

<p>
Some will argue security, that allowing raw HTML would allow people to perform cross-site scripting and other attacks, or include obscene images, or break the page layout, etc. I&#8217;m not arguing for letting users use HTML without filtering, it&#8217;s absolutely necessary. It&#8217;s difficult to protect against the <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2hhLmNrZXJzLm9yZy94c3MuaHRtbA==">wide variety</a> of attacks, but being difficult doesn&#8217;t mean it shouldn&#8217;t be done. There are excellent whitelisting libraries available that remove any excuse about rolling one&#8217;s own, like Ruby&#8217;s <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2dpdGh1Yi5jb20vcmdyb3ZlL3Nhbml0aXplLw==">Sanitize</a> and PHP&#8217;s <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL2h0bWxwdXJpZmllci5vcmcv">HTML Purifier</a>.
</p>

<p>
If you&#8217;re building a site, let your users use HTML (of course, replace newlines with &lt;br&gt; for them). A lot will already know it, there are a million free tutorials out there for them to learn it, and after using your site they&#8217;ll have a useful skill.
</p> <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=297" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2009/html-is-your-markup-language-anyways/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Redirecting Users&#8217; URLs</title>
		<link>http://push.cx/2009/redirecting-users-urls</link>
		<comments>http://push.cx/2009/redirecting-users-urls#comments</comments>
		<pubDate>Tue, 16 Jun 2009 18:46:38 +0000</pubDate>
		<dc:creator>Peter Harkins</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[human-readable]]></category>
		<category><![CDATA[URLs]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://push.cx/?p=1196</guid>
		<description><![CDATA[I got an email in response to an old post on how I designed NearbyGamer&#8216;s discussion URLs. It asked how to create readable URLs for a community site where users might edit those URLs. What happens after users have made lots and lots of edits? There are two basic strategies for keeping a changing URL [...]]]></description>
			<content:encoded><![CDATA[<p>
I got an email in response to an old post on how I designed <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL05lYXJieUdhbWVycy5jb20=">NearbyGamer</a>&#8216;s <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL3B1c2guY3gvMjAwNy9kaXNjdXNzaW9uLXVybHMtb3BhcXVlLXVzYWJsZS1hbmQtcmVhZGFibGU=">discussion URLs</a>. It asked how to create readable URLs for a community site where users might edit those URLs. What happens after users have made lots and lots of edits?
</p>

<p>
There are two basic strategies for keeping a changing URL pointing to the same content. Either only part of the URL changes and you look things up by the stable piece (as with the slugs in my previous blog post) or you keep track of old identifiers with pointers to their current identifiers.
</p>

<p>
On NearbyGamers, <a href="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?url=aHR0cDovL05lYXJieUdhbWVycy5jb20vdGFncw==">tags</a> are used to identify what games players are open to playing. But there are a huge number of variations: the game Dungeons and Dragons might be listed as D&#038;D, DND, D&#038;D 4, D&#038;D 4th ed., or many more (and that&#8217;s before spelling errors).
</p>

<p>
To deal with this, I borrowed a mechanism from Wikipedia. Users can edit a tag to redirect it to another (which may not have a redirect set to a third, to prevent all sorts of annoying problems). In short, the Tag object might just be used for its column pointing to another Tag.
</p>

<p>
This is functionally equivalent to having a table of redirects. When a request comes in for a particular Tag, I could check a TagRedirect table to see if that tag appears in the <kbd>from</kbd> column and redirect the visitor to the Tag named by the <kbd>to</kbd> column.
</p>

<p>
Redirects are one of the ways your app will have to scale to meet users&#8217; activity. Thinking about redirects as an explicit table makes it clear you have options for how to deal with it: you could add a date column and expire old entries, or limit the number of redirects one user is allowed to make (perhaps over time), or limit the number of redirects one entity allows. You could even replace this database table with a distributed key/value store like memcached (or preferably something more permanent).
</p>

<p>
So allowing users to edit URLs leads to one of three things: either you don&#8217;t allow them to edit the real identifier, you maintain a table of redirects, or you accept broken links.
</p>

<p>
NearbyGamers also uses the third strategy: if a gamer changes their handle, the URL is updated without any kind of redirecting. I considered redirects, but then no one could ever relinquish a handle.
</p>

<p>
URL design is not easy. Allowing users to influence what a URL will be is often really valuable but adds to the difficulty of designing your URLs. This is one of the interesting bits of computer programming where there isn&#8217;t a single answer, you have to pick your tradeoffs to match your needs.
</p> <img src="http://push.cx/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1196" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://push.cx/2009/redirecting-users-urls/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

