<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title></title>
    <atom:link href="http://timshadel.com/feed.xml" rel="self" type="application/rss+xml"/>
    <link>http://timshadel.com/</link>
    <description></description>
    <pubDate>Wed, 16 Jan 2019 23:33:59 +0000</pubDate>
    
      <item>
        <title>Add Events to the Calendar on iOS</title>
        <link>http://timshadel.com/how-to/add-events-to-the-calendar-on-ios.html</link>
        <guid isPermaLink="true">http://timshadel.com/how-to/add-events-to-the-calendar-on-ios.html</guid>
        <description>&lt;p&gt;So you have event information that you want to put into a calendar on iOS. Let’s say you have a local struct that keeps track of events your app manages, like football games.&lt;/p&gt;

&lt;!--more--&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MyEvent&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;startTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSDate&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;endTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSDate&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Perhaps you’ve got a button in your interface that lets a user add any football game to their favorites list, and when they do you’ll try adding it to their calendar as well.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;addedToFavorites&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;addEventToUserCalendar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;removeEventFromUserCalendar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;First we’ll get our authorization status for working with calendar events. From there we’ll ask the user for permission to work with their calendar if we’ve never done so before. Once we have authorization, then the fun begins.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;addEventToUserCalendar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;myEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MyEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EKEventStore&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;authorizationStatusForEntityType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;eventStore&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EKEventStore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NotDetermined&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;eventStore&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;requestAccessToEntityType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;authorized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;authorized&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nf&quot;&gt;showEventInUserCalendar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Authorized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;showEventInUserCalendar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Restricted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Denied&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We’ll create a calendar event from our own event struct and then present a view controller that will let the user edit and save it to the calendar of their choice.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;showEventInUserCalendar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;myEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Create calendar event&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;calendarEvent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EKEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;eventStore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventStore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;calendarEvent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myEvent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;calendarEvent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;startDate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myEvent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;startTime&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;calendarEvent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endDate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myEvent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;endTime&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fifteenMinutesBefore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSTimeInterval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;calendarAlarm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EKAlarm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;relativeOffset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fifteenMinutesBefore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;calendarEvent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;addAlarm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calendarAlarm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Setup edit view controller&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;editViewController&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EKEventEditViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;editViewController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eventStore&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventStore&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;editViewController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calendarEvent&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;editViewController&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;editViewDelegate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;presentViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;editViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;completion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That will show the user our event data and let them choose how to edit it before saving the event to the calendar of their choice.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://timshadel.com/img/post/2016-add-events-to-the-ios-calendar-screenshot.png&quot; alt=&quot;Screenshot of the calendar item being edited&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Once the user saves the event to their calendar, we’ll get a callback.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;MyViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EKEventEditViewDelegate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;eventEditViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EKEventEditViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;didCompleteWithAction&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EKEventEditViewAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;calendarEvent&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;controller&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Saved&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// Save calendarEvent.eventIdentifier somewhere nice&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;dismissViewControllerAnimated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;completion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Later we can delete the event from their calendar using the identifier we saved. To simplify, I’ve left the authorization checks out of this method.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;removeEventFromUserCalendar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;calendarEventId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Retrieve it from somewhere nice&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;event&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventStore&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;eventWithIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calendarEventId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eventStore&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;removeEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;ThisEvent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Those are the basics of taking the custom event data from your app and adding them to the user’s calendar.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What kind of events are you saving? Leave a comment below to let me know.&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Thu, 28 Jan 2016 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Super Quick Archiving with Mail.app on OS X Lion</title>
        <link>http://timshadel.com/how-to/super-quick-archiving-with-mail-app-on-os-x-lion.html</link>
        <guid isPermaLink="true">http://timshadel.com/how-to/super-quick-archiving-with-mail-app-on-os-x-lion.html</guid>
        <description>&lt;p&gt;In my own personal ups and downs to hit &lt;a href=&quot;http://inboxzero.com/&quot; title=&quot;Merlin Mann's excellent InboxZero&quot; target=&quot;_blank&quot;&gt;InboxZero&lt;/a&gt; every day, I find that the silly tool that helps me the most is having a keystroke to move the current email into an Archive folder.&lt;/p&gt;

&lt;p&gt;I used to use &lt;a href=&quot;http://www.hawkwings.net/2005/10/21/getting-things-done-in-apple-mail/&quot; title=&quot;Getting Things Done in Apple Mail&quot; target=&quot;_blank&quot;&gt;&lt;em&gt;Mail-Act-On&lt;/em&gt;&lt;/a&gt;, but was too cheap to pay for it. Now, in &lt;em&gt;Mail.app&lt;/em&gt; of &lt;a href=&quot;http://www.apple.com/macosx/&quot; title=&quot;OS X Lion&quot; target=&quot;_blank&quot;&gt;OS X Lion&lt;/a&gt;, it’s dead simple to do, no extra purchase required. Lion’s copy of mail now has an &lt;code class=&quot;highlighter-rouge&quot;&gt;Archive&lt;/code&gt; button that will create an Archive folder if it doesn’t exist already, and then move the current message there. Here’s how to get a shortcut key assigned to it:&lt;/p&gt;

&lt;p&gt;First, open up &lt;em&gt;System Preferences&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://timshadel.com/wp-content/uploads/2011/08/SystemPrefs.png&quot;&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2011/08/SystemPrefs.png&quot; alt=&quot;&quot; title=&quot;System Preferences&quot; width=&quot;575&quot; class=&quot;aligncenter size-full wp-image-358&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Next, go into the &lt;code class=&quot;highlighter-rouge&quot;&gt;Keyboard PrefPane&lt;/code&gt;. Select the &lt;code class=&quot;highlighter-rouge&quot;&gt;Keyboard Shortcuts&lt;/code&gt; tab near the top.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://timshadel.com/wp-content/uploads/2011/08/KeyboardPrefPane.png&quot;&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2011/08/KeyboardPrefPane.png&quot; alt=&quot;&quot; title=&quot;Keyboard PrefPane&quot; width=&quot;575&quot; class=&quot;aligncenter size-full wp-image-362&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now select &lt;code class=&quot;highlighter-rouge&quot;&gt;Application Shortcuts&lt;/code&gt; in the left column, and then click the &lt;code class=&quot;highlighter-rouge&quot;&gt;'+'&lt;/code&gt; sign at the bottom of the right-hand column to add a new application keyboard shortcut. In the top drop down box, choose &lt;code class=&quot;highlighter-rouge&quot;&gt;Mail&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://timshadel.com/wp-content/uploads/2011/08/NewShortcutKey.png&quot;&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2011/08/NewShortcutKey.png&quot; alt=&quot;&quot; title=&quot;New Shortcut Key&quot; width=&quot;575&quot; class=&quot;aligncenter size-full wp-image-365&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now these keyboard shortcuts rely upon selecting an exact menu item from the application. So here’s what the &lt;code class=&quot;highlighter-rouge&quot;&gt;Message menu&lt;/code&gt; looks like in &lt;em&gt;Mail.app&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://timshadel.com/wp-content/uploads/2011/08/MailArchiveMenuItem.png&quot;&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2011/08/MailArchiveMenuItem.png&quot; alt=&quot;&quot; title=&quot;Mail Archive Menu Item&quot; width=&quot;319&quot; height=&quot;425&quot; class=&quot;aligncenter size-full wp-image-363&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are two things to notice: first, there’s no shortcut listed on the right-hand side, and second, the menu item text we need is simply &lt;code class=&quot;highlighter-rouge&quot;&gt;Archive&lt;/code&gt;. So now we’ll go back to the &lt;code class=&quot;highlighter-rouge&quot;&gt;Keyboard PrefPane&lt;/code&gt; and type that into the &lt;code class=&quot;highlighter-rouge&quot;&gt;Menu Title text box&lt;/code&gt;. Next click into the &lt;code class=&quot;highlighter-rouge&quot;&gt;Keyboard Shortcut text box&lt;/code&gt; and type in your preferred shortcut key. I used &lt;code class=&quot;highlighter-rouge&quot;&gt;Ctrl + A&lt;/code&gt;, which is displayed as &lt;code class=&quot;highlighter-rouge&quot;&gt;^A&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://timshadel.com/wp-content/uploads/2011/08/FinishNewShortcutKey.png&quot;&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2011/08/FinishNewShortcutKey.png&quot; alt=&quot;&quot; title=&quot;Finish New Shortcut Key&quot; width=&quot;575&quot; class=&quot;aligncenter size-full wp-image-361&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, switch back to &lt;em&gt;Mail.app&lt;/em&gt; and check out the &lt;code class=&quot;highlighter-rouge&quot;&gt;Messages menu&lt;/code&gt; again. The &lt;code class=&quot;highlighter-rouge&quot;&gt;Archive menu item&lt;/code&gt; now shows your keyboard shortcut key on the right hand side.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://timshadel.com/wp-content/uploads/2011/08/MailArchiveMenuWithShortcut.png&quot;&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2011/08/MailArchiveMenuWithShortcut.png&quot; alt=&quot;&quot; title=&quot;Mail Archive Menu With Shortcut&quot; width=&quot;319&quot; height=&quot;425&quot; class=&quot;aligncenter size-full wp-image-364&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now take it for a test drive: select an email you’d like to archive and then hit your shortcut (&lt;code class=&quot;highlighter-rouge&quot;&gt;^A&lt;/code&gt; for me). You should see your email safely disappear into your Archive folder. And for bonus points, if you have more than one email account, select two emails sent to &lt;strong&gt;different accounts&lt;/strong&gt;. When you hit your shortcut key to archive them, each will go to the correct account’s Archive folder. Booyah!&lt;/p&gt;

&lt;p&gt;With that set, I can fly through my Inbox deleting and archiving as fast as possible, leaving behind only the emails that I really have to think about and extract meaning from.&lt;/p&gt;

&lt;p&gt;Processing email on my iPhone is just a losing battle after having this setup. Now go on. Get going on it. You’ll feel like a ninja.&lt;/p&gt;

</description>
        <pubDate>Sat, 27 Aug 2011 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>The Best Way to Install Hudson on Mac OS X</title>
        <link>http://timshadel.com/how-to/the-best-way-to-install-hudson-on-mac-os-x.html</link>
        <guid isPermaLink="true">http://timshadel.com/how-to/the-best-way-to-install-hudson-on-mac-os-x.html</guid>
        <description>&lt;p&gt;For the short-attention spans (like mine):&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew install hudson
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;OK. &lt;ins datetime=&quot;2010-12-28T03:10:36+00:00&quot;&gt;That should work now.&lt;/ins&gt; &lt;del datetime=&quot;2010-12-28T03:10:36+00:00&quot;&gt;That may not work…yet. There are details after the jump for those who don’t want to wait for &lt;a href=&quot;https://github.com/mxcl/homebrew/pull/3706&quot;&gt;the pull request&lt;/a&gt; to go through.&lt;/del&gt; Oh, and read the directions after running that command to get it to launch automatically.&lt;/p&gt;

&lt;p&gt;&lt;ins datetime=&quot;2010-12-28T03:10:36+00:00&quot;&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; &lt;a href=&quot;http://github.com/mikemcquaid&quot;&gt;mikemcquaid&lt;/a&gt; was super fast and the changes are merged. Read the details below for more info both on what happens, the basic approach, and how you can &lt;code&gt;brew install&lt;/code&gt; your own version.&lt;/ins&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;For some reason I’ve had a thing for making &lt;a href=&quot;http://hudson-ci.org&quot;&gt;Hudson&lt;/a&gt; easier to install. Several years ago I wrote the &lt;a href=&quot;http://timshadel.com/2007/02/08/try-hudson-instead-of-cruisecontrol-the-3-minute-setup/&quot;&gt;3-minute setup guide&lt;/a&gt; which the fantastic maintainer &lt;a href=&quot;http://www.hudson-labs.org/content/about-hudson-labs&quot;&gt;Kohsuke Kawaguchi&lt;/a&gt; turned around and &lt;a href=&quot;http://weblogs.java.net/blog/kohsuke/archive/2007/02/hudson_became_s.html&quot;&gt;rolled directly into Hudson&lt;/a&gt;. I don’t think I’ve touched any other CI system since (for anything beyond a quick test drive). The configuration management group at my current workplace uses that very direct self-executing hudson version to run a couple dozen production build servers; I didn’t have anything to do with that decision, it was just simple.&lt;/p&gt;

&lt;p&gt;So, nearly 4 years later, I’ve been looking around at how to automate iPhone builds. My &lt;a href=&quot;http://bit.ly/a4qn3x&quot;&gt;Waterlogged app&lt;/a&gt; has been in the AppStore for almost a year, and has covered quite a bit of ground in feature growth in that time. It’s reasonably mature, while still fairly small as far as the code goes. I finally picked up a mid-2009 Mac mini with the intent of making it into a build server. I’ve found a number of ideas about &lt;a href=&quot;http://nachbaur.com/blog/how-to-automate-your-iphone-app-builds-with-hudson&quot;&gt;how to automate&lt;/a&gt; &lt;a href=&quot;http://blog.octo.com/en/automating-over-the-air-deployment-for-iphone/&quot;&gt;iPhone app builds&lt;/a&gt; and &lt;a href=&quot;http://stackoverflow.com/questions/2415161/over-the-air-deployment-of-iphone-app&quot;&gt;over-the-air beta deployments&lt;/a&gt;, as well as how to add &lt;a href=&quot;http://pivotallabs.com/users/amilligan/blog/articles/1321-iphone-ui-automation-tests-with-jasmine&quot;&gt;automatic&lt;/a&gt; &lt;a href=&quot;https://github.com/pivotal/cedar&quot;&gt;testing&lt;/a&gt; &lt;a href=&quot;http://alexvollmer.com/posts/2010/07/03/working-with-uiautomation/&quot;&gt;to&lt;/a&gt; that build. The first thing obviously seemed to be to install Hudson on my Mac mini.&lt;/p&gt;

&lt;p&gt;So, all the cool tool installation on Mac these days is done with &lt;a href=&quot;http://mxcl.github.com/homebrew/&quot;&gt;Homebrew&lt;/a&gt;. But &lt;code class=&quot;highlighter-rouge&quot;&gt;brew info hudson&lt;/code&gt; left me with nothing. So I rolled up my sleeves in the evening on this Christmas Day (with kids not quite in bed yet) and started to take a crack at it. I wanted Hudson installed in a default location; no thinking required. And I wanted it so that when the mini rebooted, Hudson came up automatically. That meant I needed a LaunchDaemon. After finding a few really bad ideas out there, I came across Jérôme Renard’s simple plist file. I combined that with the basics from the mongodb Homebrew Formula, and the conventions I saw in the results from the grails install, and cobbled together a first draft of the Hudson install.&lt;/p&gt;

&lt;p&gt;It’s probably less-than-ideal, but I figured I’d ship the first version, request a pull, and then let the magic of git and crowds perfect it over time. I created the Formula on my Air, pushed to GitHub, then with a few commands on my mini,&lt;/p&gt;

&lt;p&gt;I was ready to install my own Formula.&lt;/p&gt;

&lt;p&gt;and it launches now, and is setup to launch any time my user logs in. I hit it in the browser, and it came back just fine.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2010/12/hudson.png&quot; alt=&quot;&quot; title=&quot;hudson&quot; width=&quot;550&quot; height=&quot;359&quot; class=&quot;aligncenter size-full wp-image-342&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Notice that if my pull request gets merged in soon, the first part just drops off and you get left with just 3 commands:&lt;/p&gt;

&lt;p&gt;and the bottom two are given to you when you run the first one. So in the end, all you need is&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew install hudson
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Which is where we started… Merry Christmas, and Happy Building on your Mac!&lt;/p&gt;

</description>
        <pubDate>Mon, 27 Dec 2010 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Subtle Activity Cues</title>
        <link>http://timshadel.com/craftsmanship/subtle-activity-cues.html</link>
        <guid isPermaLink="true">http://timshadel.com/craftsmanship/subtle-activity-cues.html</guid>
        <description>&lt;p&gt;One of the topics that fascinates me is how to provide subtle kinds of useful information to users of software. I like sparklines, typography, and &lt;a href=&quot;http://37signals.com/svn/posts/1952-i-gave-a-talk-on-ui-fundamentals-for-programmers&quot;&gt;subtle graphic design elements&lt;/a&gt; that call attention to information with the right weight.&lt;/p&gt;

&lt;p&gt;One simple example I ran across today was the metric provided by &lt;a href=&quot;http://stackoverflow.com&quot;&gt;StackOverflow&lt;/a&gt; on my profile for the number of days I’ve visited — 195 days out of just over a year since breaking down and creating my account.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://stackoverflow.com/users/179391/tim-shadel&quot;&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2010/12/stack-overflow-profile.png&quot; alt=&quot;&quot; title=&quot;stack-overflow-profile&quot; width=&quot;470&quot; height=&quot;328&quot; class=&quot;aligncenter size-full wp-image-335&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So that’s just about right considering how frequently good questions and answers from StackOverflow show up in my Google searches. You can tell I don’t contribute a lot, and I don’t show up even every other day, but it’s not far off from that. That kind of information was surprising, since I never really thought about how many times I had come to the site.&lt;/p&gt;

&lt;p&gt;What about your site or web app, or even iPhone app? Do you have quarter-over-quarter user retention goals? Do you think that your users would suddenly realize the value they implicitly already placed on your service if they saw out of the corner of their eye how much they used it? I had that feeling. If they saw how much they cared about it in hard data, would they respond more frequently to your requests to refer their friends to you?&lt;/p&gt;

&lt;p&gt;Think about it. You might be able to tap into more power than you think with simple, subtle cues.&lt;/p&gt;

</description>
        <pubDate>Thu, 16 Dec 2010 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>CSS, Aspects, and Screencasting</title>
        <link>http://timshadel.com/leftovers/css-aspects-and-screencasting.html</link>
        <guid isPermaLink="true">http://timshadel.com/leftovers/css-aspects-and-screencasting.html</guid>
        <description>&lt;p&gt;I recently came across an old draft post from 2007 that I never published. It looks finished enough to simply push it out as-is. While it was obviously written before the explosion of CSS frameworks and tools like Blueprint and Compass, those don’t really have much impact on the core of what I was saying. I hope you find it useful…&lt;/p&gt;

&lt;p&gt;–Tim&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;This morning I read a post by Jon Udell that ignited a series of latent thoughts I’ve had, mostly centered around CSS, aspects, and screencasting.&lt;/p&gt;

&lt;p&gt;In his post, &lt;a href=&quot;http://blog.jonudell.net/2007/01/22/matthew-levines-holy-grail/&quot;&gt;Matthew Levine’s holy grail&lt;/a&gt;, Jon praises the theory of CSS but bemoans the drudgery that so many of us not-a-designer-but-geek-enough-to-try types face at some point or other:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;To be honest, although I’m hugely fond of CSS styling, I’ve always struggled with CSS layouts, and I know I’m not the only one in that boat. When you read the explanation in Matthew’s article, you can see why. CSS layout is like one of those games where you slide 15 tiles around in a 16-square matrix. In principle it is a declarative language, but in practice the techniques are highly procedural: Step 1, Step 2, etc.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Jon goes on to request a pattern library for CSS layouts, and while I think it’s a great idea I don’t think it’s enough. In my many years of web programming experience few things been more intriguing and challenging as deconstructing a complex web design from someone else and distilling it to the essentials. In the end, we muddle through, leaving unnecessary HTML and CSS constructs littered throughout our new site. Data needs evolve for the site, invoking the corresponding evolutionary change in the HTML and CSS constructs. The ebb and flow of change ultimately builds up enough sediment in our design that, like your old water heater, you simply throw it out and start afresh.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Why is it so complicated? Isn’t it just colors and a bit of structure? To get good at evolutionary web design takes several things. I believe that first it takes time to understand how web designers approach the process of building a particular template. On top of that it takes a clear understanding of the unbreakable link between HTML structure and CSS — a coupling so tight and so loose at the same time.&lt;/p&gt;

&lt;p&gt;For starters, the design process is sufficiently opaque to obscure the reasoning for certain elements. (Is this HTML construct here only to achieve a certain feature? Is that CSS construct there for the same reason, or does it play multiple roles?) Learning more of the tacit knowledge of the evolutionary web design is helpful.&lt;/p&gt;

&lt;p&gt;One piece of the puzzle is to understand the design process more in depth. Jon’s been the major proponent of screencasts for a long time. He’s said in his article &lt;a href=&quot;http://weblog.infoworld.com/udell/2006/09/19.html&quot;&gt;Screencasting of tacit knowledge&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote class=&quot;pullQuote&quot;&gt;One of the things that I&amp;#8217;ve known tacitly, but never articulated, is that screencasting can be an excellent way to transmit tacit knowledge.&lt;/blockquote&gt;

&lt;p&gt;But one of the challenges is transmitting the kind of tacit knowledge involved in CSS design work is that it takes place over a long period of time — &lt;em&gt;way&lt;/em&gt; to long to merit a screencast. I recently stumbled across another form of transmitting that kind of tacit knowledge, though. It seems like the time-lapse cousin to the screencast. &lt;a href=&quot;http://mboffin.com/post.aspx?id=1619&quot; title=&quot;MBoffin.com - Designline - A Design Timeline&quot;&gt;Dylan Bennett created&lt;/a&gt; what he calls a &lt;em&gt;designline&lt;/em&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;To create this designline, I took a screenshot basically every time I saved my HTML file. I’m one of those people who impulsively hits Ctrl-S after every tiny little change, so you end up seeing every little change made to the file as it goes. I started out with a blank text file and I go all the way to a completed site design. Check it out.&lt;/p&gt;

  &lt;p&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2010/12/designline-openair.gif&quot; alt=&quot;Time-lapse evolution of a web site design&quot; /&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;While CSS has a declarative format, as Jon mentions above, to me it also has the feel of an aspect-oriented language in that a single declaration may cut across a multitude of unrelated elements. One single element may have &lt;a href=&quot;http://weblog.infoworld.com/udell/2004/02/09.html#a913&quot; title=&quot;Multivalued CSS class attributes&quot;&gt;multiple CSS classes&lt;/a&gt; associated with it.&lt;/p&gt;

</description>
        <pubDate>Mon, 06 Dec 2010 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Query Your Filesystem</title>
        <link>http://timshadel.com/leftovers/query-your-filesystem.html</link>
        <guid isPermaLink="true">http://timshadel.com/leftovers/query-your-filesystem.html</guid>
        <description>&lt;p&gt;Queries are a way of asking a computer system questions. (I heard you say ‘duh!’) You’ve probably done this lots in SQL to ask your database questions. How many members have this condition? How much money was sent to these people in August? But how about this one: Which file has the bean named ‘myCrazyService’ in it? Or, How many projects refer to the old version of ‘projectFastMoving’? For these questions you should turn to the *nix-like file utilities.&lt;/p&gt;

&lt;p&gt;Standard *nix tools can be used to create queries that your filesystem can answer. Let’s start with &lt;code class=&quot;highlighter-rouge&quot;&gt;find&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;the-find-utility&quot;&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;find&lt;/code&gt; utility&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;find&lt;/code&gt; command lets you locate files that are named in a specific way, and that have certain file attributes. Let’s look at an example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-iname&lt;/span&gt; SpriNg.xml&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This query searches the current directory, and looks for files with names like: spring.xml, Spring.xml, or sprinG.xml. The &lt;code class=&quot;highlighter-rouge&quot;&gt;i&lt;/code&gt; in &lt;code class=&quot;highlighter-rouge&quot;&gt;iname&lt;/code&gt; means that the pattern will use a case-insensitive comparison when matching against existing files. Let’s try another:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; proj&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;.xml &lt;span class=&quot;nt&quot;&gt;-maxdepth&lt;/span&gt; 2&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This code searches the current directory, and will go down only 2 folders below this one in search of matches. It will look for files named like: projector.xml, project.xml, and proj2.xml. Limiting the depth can greatly speed your search. So can starting at a lower level of the directory structure.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h3 id=&quot;add-grep-to-your-bucket&quot;&gt;Add &lt;code class=&quot;highlighter-rouge&quot;&gt;grep&lt;/code&gt; to your bucket&lt;/h3&gt;

&lt;p&gt;Now that you’ve located the set of files under suscpicion, it’s time to execute your unwarrented search. For example, if you’re looking for which projects depend on my-shared-code then your query might look something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; project.xml &lt;span class=&quot;nt&quot;&gt;-maxdepth&lt;/span&gt; 2 &lt;span class=&quot;nt&quot;&gt;-exec&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; my-shared-code &lt;span class=&quot;o&quot;&gt;{}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;There’s a lot going on here. The first half of the find command should be fairly familiar. The last half invokes a program for each result found, using the &lt;code class=&quot;highlighter-rouge&quot;&gt;-exec&lt;/code&gt; parameter. Everything from that point until the semicolon is considered part of the executed command. The &lt;code class=&quot;highlighter-rouge&quot;&gt;{}&lt;/code&gt;‘s indicate where the filename should be substituted at execution time. So the resulting command runs &lt;strong&gt;as if&lt;/strong&gt; it were something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-sh&quot; data-lang=&quot;sh&quot;&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; my-shared-code &lt;span class=&quot;se&quot;&gt;\w&lt;/span&gt;ork&lt;span class=&quot;se&quot;&gt;\m&lt;/span&gt;y-products&lt;span class=&quot;se&quot;&gt;\m&lt;/span&gt;yproduct&lt;span class=&quot;se&quot;&gt;\t&lt;/span&gt;runk&lt;span class=&quot;se&quot;&gt;\m&lt;/span&gt;yproject&lt;span class=&quot;se&quot;&gt;\p&lt;/span&gt;roject.xml&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The option used in grep is a lowercase &lt;code class=&quot;highlighter-rouge&quot;&gt;L&lt;/code&gt;. It tells grep to list only the filename whose contents match, and not the line contents that triggered the match.&lt;/p&gt;

&lt;h3 id=&quot;stuck-on-windows&quot;&gt;Stuck on Windows?&lt;/h3&gt;

&lt;p&gt;Try &lt;a href=&quot;http://sourceforge.net/projects/console/&quot;&gt;Console 2&lt;/a&gt; or &lt;a href=&quot;http://www.cygwin.com/&quot;&gt;Cygwin&lt;/a&gt;. I’ve been &lt;a href=&quot;http://timshadel.com/2006/11/15/election-results-mac-over-ubuntu-in-a-landslide&quot;&gt;exclusively on Mac for over 4 years&lt;/a&gt;, so I can’t help you much more than that. &lt;img src=&quot;http://timshadel.com/wp-includes/images/smilies/icon_smile.gif&quot; alt=&quot;:-)&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;go-try-it&quot;&gt;Go try it&lt;/h3&gt;

&lt;p&gt;Now go try it. See what kinds of queries you can write. See which take a long time, and how you can focus them to get the info you need in a reasonable time frame. Enjoy!&lt;/p&gt;

</description>
        <pubDate>Fri, 03 Dec 2010 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Design Example: MobileMe Bad Password</title>
        <link>http://timshadel.com/impressions/design-example-mobileme-bad-password.html</link>
        <guid isPermaLink="true">http://timshadel.com/impressions/design-example-mobileme-bad-password.html</guid>
        <description>&lt;p&gt;I love to find examples of small details around the web that impress me in their innovation, craftsmanship, beauty, or structure. Here’s one I ran across last week:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://timshadel.com/wp-content/uploads/2010/11/MobileMe-Forgot-Password1.png&quot;&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2010/11/MobileMe-Forgot-Password-e1291052410874.png&quot; alt=&quot;&quot; title=&quot;MobileMe Forgot Password&quot; width=&quot;589&quot; height=&quot;385&quot; class=&quot;aligncenter size-full wp-image-313&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you type in a bad password on &lt;a href=&quot;http://me.com&quot;&gt;MobileMe&lt;/a&gt;, it doesn’t simply show an error dialog, but animates in a bubble that points to the password box and hovers over the existing text. This is a nice departure from error messages that insert themselves into the 2D HTML layout that’s typical of most websites.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;This provides that modern feel through layering, shadows, and animation that make it feel like the iPhone — human in its approach to UI interactions with you. All the subtle cues are there, and all the mechanisms to help you adjust to the new layout naturally. I really like it.&lt;/p&gt;

&lt;p&gt;I captured and annotated this screenshot using &lt;a href=&quot;http://awesomescreenshot.com/&quot;&gt;Awesome Screenshot&lt;/a&gt; (&lt;a href=&quot;https://extensions.apple.com/&quot;&gt;available for Safari&lt;/a&gt;, and &lt;a href=&quot;https://chrome.google.com/extensions/detail/alelhddbbhepgpmgidjdcjakblofbmce?hl=en&quot;&gt;Chrome&lt;/a&gt;). I like to grab screenshots with it, and then annotate them with text and arrows, then drop them into &lt;a href=&quot;http://evernote.com&quot;&gt;Evernote&lt;/a&gt; and let it index the text it sees inside the image. That way I get notes close to the things I care about, I can point instead of say “that box up above the blue one”, and I don’t lose the benefits of searching my notes. Overall it’s a pretty effective way for me to take notes about designs I like around the web.&lt;/p&gt;

&lt;p&gt;I think I’ll try to snag an example or two each week for a while and post them here in my &lt;a href=&quot;http://timshadel.com/categories/impressions/&quot;&gt;Impressions&lt;/a&gt; area to share with you.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Got any favorite design examples? Leave a comment and share with everyone!&lt;/em&gt;&lt;/p&gt;

</description>
        <pubDate>Tue, 30 Nov 2010 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Review: Balsamiq</title>
        <link>http://timshadel.com/impressions/review-balsamiq.html</link>
        <guid isPermaLink="true">http://timshadel.com/impressions/review-balsamiq.html</guid>
        <description>&lt;h2 id=&quot;balsamiq-seems-perfect-for-quick-impressions&quot;&gt;Balsamiq seems perfect for quick impressions&lt;/h2&gt;

&lt;p&gt;The bottom line? &lt;a href=&quot;http://balsamiq.com/&quot;&gt;Balsamiq&lt;/a&gt; is even cooler than it’s great first impression — you should use it. Bugs? A few. Do they impact me? Not enough to care. Support? Very good. In short: buy it. It’s worth it.&lt;/p&gt;

&lt;h2 id=&quot;when-to-use-it&quot;&gt;When to use it.&lt;/h2&gt;

&lt;p&gt;Anytime you want to talk with someone about how something should work. And especially when you’re comparing it to how something works already.&lt;/p&gt;

&lt;p&gt;I’ve been using Balsamiq for the last several months. When I say that, I also need to give a bit of explanation. You see, it’s not the kind of application that begs you for daily use. At least not to me. But it’s the kind of app that just aches to be used at certain key points — when you need to -communicate- help someone get what you’re thinking, or when you need to explore that idea that seems just right in your head (Balsamiq will have a way of giving you usable feedback quickly — maybe you really haven’t thought things out so well…), or in a dozen other scenarios that come up.&lt;/p&gt;

&lt;h2 id=&quot;think-of-it-as-test-first-ui-design&quot;&gt;Think of it as Test-First UI design.&lt;/h2&gt;

&lt;p&gt;Don’t sit down and start hacking out your rhtml, haml, jsp, or whatever. Mock it up first with Balsamiq. I was amazed at how easy it was to get a decent sketch of our existing website with it, and how quickly my team could recognize what I wanted to do to it with before and after sketches. The conversation about what I wanted went like this, “Here’s our current site. Can everyone recognize it? Good. So here’s what I’m thinking we should do. [5 min conversation about the idea, backend implications, etc] The conversation stayed entirely focused on the idea I was proposing, and wasn’t distracted by the sketch mechanics.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;p&gt;Balsamiq enabled the conversation in an interesting way. It was a bit different from a whiteboard. I originally thought that I’d use Balsamiq but worried that whiteboard would be more agile, more practical for the space that I thought this tool was written for. Over a couple months of using this tool, I found that wasn’t the case. I use the whiteboard all the time still, but I found that the whiteboard isn’t a tool that helps me think &lt;em&gt;about&lt;/em&gt; my idea. I’ve seen more productive conversations around a Balsamiq mockup than around a whiteboard. Whiteboard conversations I’ve had seem more half-baked now that I have something else to compare them to. I think a lot of that has to do with forethought. Balsamiq hits a sweet spot where you feel like it prods you to think about your idea &lt;em&gt;just&lt;/em&gt; enough to get it decently clear, but because it looks sketchy you don’t get lost in the loop of trying to make it just perfect. It’s enough to have the conversation you want to have.&lt;/p&gt;

&lt;p&gt;Try it out and see what kinds of conversations you have with the mockups it generates. It just may surprise you.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Have any experiences with Balsamiq? Drop a comment down below.&lt;/em&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 29 Nov 2010 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>iPhone Icons By Verb</title>
        <link>http://timshadel.com/leftovers/iphone-icons-by-verb.html</link>
        <guid isPermaLink="true">http://timshadel.com/leftovers/iphone-icons-by-verb.html</guid>
        <description>&lt;p&gt;I’ve had an iPhone for a while. I’ve had 3 of the 4 versions, actually. I’m trying something with the folders introduced back in iOS 4: I put &lt;strong&gt;every&lt;/strong&gt; app into a folder, even Phone and Safari. Yeah, it’s a bit weird, I think. But it’s forced a new mental process that I like so far.&lt;/p&gt;

&lt;p&gt;I have to think about why I unlocked my phone.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Before I’d grab my phone to look up a phone number and scan my email instead. I’d need to check my bank account and find I’d be surfing the stats of Waterlogged usage for the day. All good stuff. None of it what I intended.&lt;/p&gt;

&lt;p&gt;So I put together folders, not by topic, but by verb. I now have to say to myself, I want to &lt;em&gt;look up&lt;/em&gt; a contact so I can send it to John.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://timshadel.com/wp-content/uploads/2010/11/20101124-092552.jpg&quot;&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2010/11/20101124-092552.jpg&quot; alt=&quot;&quot; class=&quot;alignnone size-full&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Amazingly, my apps can all fit on two iPhone screens, or a single iPad screen. I haven’t used the search screen to find an app, and I haven’t needed to check multiple folders to find the app I wanted. So far, it’s worked way better for me than “this screen is for games, and this screen is for productivity” ever did before. &lt;img src=&quot;http://timshadel.com/wp-includes/images/smilies/icon_smile.gif&quot; alt=&quot;:-)&quot; class=&quot;wp-smiley&quot; /&gt;&lt;/p&gt;

&lt;p&gt;How do you organize your iPhone apps?&lt;/p&gt;

</description>
        <pubDate>Fri, 26 Nov 2010 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Grails CLI seems slow</title>
        <link>http://timshadel.com/impressions/grails-cli-seems-slow.html</link>
        <guid isPermaLink="true">http://timshadel.com/impressions/grails-cli-seems-slow.html</guid>
        <description>&lt;p&gt;So I’m picking up some &lt;a href=&quot;http://grails.org&quot;&gt;Grails&lt;/a&gt; for a consulting gig, and as I’m trying out some of the basics, I feel like the Groovy execution of the Rails-equivalent commands is &lt;em&gt;root-canal-painfully-slow&lt;/em&gt;. Check out these timings:&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;This is why I’m always skeptical of JVM &lt;em&gt;dynamic&lt;/em&gt; languages — authors seem so bent on keeping Java that they are happy with the amount of improvement over their old world and left blind to how poorly it performs in absolute comparison to something else: where “performs” may mean syntax clarity, execution speed, or some other measure.&lt;/p&gt;

&lt;p&gt;I realize I’m a Ruby and iPhone fanboy, but I like Erlang too, and I’m still in the deliberation stage on Scala. But while I like some things with Groovy so far, there’s nothing impressive except that it tries to make Java kinda like ruby, but keep the parentheses (usually) and leave {}’s around.&lt;/p&gt;

&lt;p&gt;But this is day 2 of playing with it. We’ll see how it fares as I get some real development done.&lt;/p&gt;
</description>
        <pubDate>Mon, 22 Nov 2010 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>My Philosophy for Choosing git &amp;#038; GitHub over Mercurial &amp;#038; BitBucket</title>
        <link>http://timshadel.com/impressions/my-philosophy-for-choosing-git-github-over-mercurial-bitbucket.html</link>
        <guid isPermaLink="true">http://timshadel.com/impressions/my-philosophy-for-choosing-git-github-over-mercurial-bitbucket.html</guid>
        <description>&lt;p&gt;This is taken from an argument I made back in November for why our entire company should adopt git. There may be errors in it, and it’s fairly out of date. Given those caveats, I hope it’s useful.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;In short, I choose git and github based on my beliefs about software development at the organizational and individual levels.&lt;/p&gt;

&lt;h2 id=&quot;as-a-software-craftsman-i-believe-in-sharp-tools&quot;&gt;As a software craftsman, I believe in sharp tools&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;Tools amplify your talent. The better your tools, and the better you know how to use them, the more productive you can be. […]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Many new programmers make the mistake of adopting a single power tool, such as a particular integrated development environment (IDE), and never leave its cozy interface. This really is a mistake. We need to be comfortable beyond the limits imposed by an IDE. The only way to do this is to keep the basic tool set sharp and ready to use.
– The Pragmatic Programmer, Chapter 3&lt;/p&gt;
&lt;/blockquote&gt;

&lt;!--more--&gt;

&lt;p&gt;While Mercurial provides a command-line tool, it’s interface is limited. Git provides a more rich set of tools for me to poke through my versioned set of source code. Doing so gives me powerful ways to solve unanticipated problems that will be of great importance at some point in the future. Choosing git now lets us prepare for those moments when performance of a difficult operation will be required.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We need to let our craftsmen work with sharp tools, rather than protect them from themselves.
– Bruce Tate, author and programmer&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;i-believe-in-people-over-process&quot;&gt;I believe in people over process&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;“Individuals and interactions over processes and tools” – The Agile Manifesto&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Given a choice of two tools, one of which favors interactions and empowers individuals more than the other, I will choose the one that empowers nearly every time since I believe that trusting my peers and coaching each other in the use of a powerful concept or tool will lead to a better result overall.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“There is nothing that motivates, or inspires, people like having trust extended to them. When it is, people don’t need to be managed or supervised; they manage themselves.” – Stephen R. M. Covey, &lt;a href=&quot;http://amzn.to/cRCuZY&quot;&gt;The SPEED of Trust&lt;/a&gt;, p. 227&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Git makes it fast to switch between local forks of code. Doing so it shortens the process of forking, empowering people by reducing the process around keeping track of all of the forks they use. It makes the personal pain less, so that they fork more often and when needed instead of when the benefit outweighs the noticeable cost.&lt;/p&gt;

&lt;h2 id=&quot;i-believe-in-optimizing-the-common-cases-of-individual-use&quot;&gt;I believe in optimizing the common cases of individual use&lt;/h2&gt;

&lt;p&gt;Git makes it very fast to switch between local forks of code. It is very fast to clone a remote repo over the git protocol. It is harder to setup a central server using the git protocol. The common cases are clones and switches. The less common case is setting up server infrastructure for use among teams of individuals. GitHub innovates around this space.&lt;/p&gt;

&lt;h2 id=&quot;i-believe-in-making-broad-work-across-an-organization-globally-visible&quot;&gt;I believe in making broad work across an organization globally visible&lt;/h2&gt;

&lt;p&gt;Discovery and discoverability are the hallmarks of communication, serendipitous invention, and spontaneous collaboration. They are the heart of tools in the agile movement such as Continuous Integration, Big Visible Charts, and Collective Code Ownership. These principles are built on the idea that we must trust everyone involved in building our software to both see the code, see the progress we’re making in building our software, and make changes to any code that they need to to push the software forward. I believe extending that trust is absolutely required if we are to develop software at industry speed.&lt;/p&gt;

&lt;p&gt;If we are to develop software at that speed, we need a way for people not only to extend that trust, but to do so in ways that are discoverable by others in the sea of changes that occur when a large organization undertakes writing software. Collaborative community-based tools, like GitHub, built on solid distributed software tools are required to make the host of conceptual development streams visible and discoverable to individual front-line developers.&lt;/p&gt;

&lt;p&gt;By using innovations such as following fellow developers, following specific forks, and reading peer comments about specific commits we empower developers to discover community knowledge around our massively changing source base in powerful ways that they cannot simply by interacting with the source control tool.&lt;/p&gt;

&lt;p&gt;By choosing a community tool built on an infrastructure and core tool community that prods individual developers to craft the ways they publish their changes to others, we then get individual developers communicating meaningful semantic changes to their peers in ways discoverable chunks sized to the optimal granularity of the discovery scope and mechanism.&lt;/p&gt;

&lt;h2 id=&quot;i-believe-in-programming-on-purpose-and-not-by-coincidence&quot;&gt;I believe in Programming on Purpose, and Not By Coincidence&lt;/h2&gt;

&lt;p&gt;Part of that belief is that developers should make informed, conscious choices about their actions at every step of the way. They should choose indexes wisely in their database, choose their abstractions correctly given the realities of their software and its environment, and craft their source code history consciously to give those that follow a clear picture of the conceptual evolution of their code.&lt;/p&gt;

&lt;p&gt;I believe that using a tool born out of a culture that believes in communicating intent over preserving immutability will shape a developer’s thinking more correctly for harnessing that powerful communication possibility than using a tool from a community that is generally opposed to it. Freezing the code in its coincidental flow of changes by making history immutable disallows a logical communication of changes in favor of a physical communication. A culture that promotes historical immutability will always promote to the developer that the preservation of coincidental timelines above conceptual change communication.&lt;/p&gt;

&lt;p&gt;This is a powerful, principled, and irreconcilable difference in the philosophical underpinnings among the tool communities. The blogs and manuals of Mercurial heavily favor immutability over communicating intent.&lt;/p&gt;

&lt;h2 id=&quot;as-a-minimalist-and-computer-science-advocate-i-believe-in-very-clean-data-structures&quot;&gt;As a minimalist and computer science advocate, I believe in very clean data structures&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;“The programmer at wit’s end for lack of space can often do best by disentangling himself from his code, rearing back, and contemplating his data. Representation &lt;em&gt;is&lt;/em&gt; the essence of programming” – Fred Brooks, &lt;a href=&quot;http://amzn.to/cxk698&quot;&gt;The Mythical Man-Month&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In Chapter 3 of the classic book &lt;a href=&quot;http://amzn.to/9bR8Zv&quot;&gt;Programming Pearls&lt;/a&gt;, Jon Bentley covers data structures and illustrates both in striking detail and in beautiful simplicity how the underlying data structures impact the performance of a program. I would add that it is also clear how that structure alters the possibilities of new code that can use that data and the minds of the programmers approaching it.&lt;/p&gt;

&lt;p&gt;Git’s simplistic data structure allowed its initial approach to version a source tree to grow in unexpected ways:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Its compression algorithm is better than any other tool because it is not compressing data structured around a filename.&lt;/li&gt;
  &lt;li&gt;It was trivial to take advantage of the OS filesystem cache by allowing an in-place switch of a working copy from one branch to another by realizing that each local branch is a pointer to into its blob graph.&lt;/li&gt;
  &lt;li&gt;The above makes it trivial to add on the concepts of remote references, making it possible for developers to see locally (without a network) the evolution of a remote repository. Such is not available in Mercurial. The core data structure of Git made this evolutionary functionality possible.&lt;/li&gt;
  &lt;li&gt;By focusing around a specific data structure and following the UNIX tradition of composable programs, git evolved a structure allowing for custom pluggable merge and difference drivers. This, combined with the simple data structure giving a list of parents instead of exactly two, produced the octopus merge tool that can take many separate branches and merge them all. This tool seems most often used in larger projects, and I anticipate it may prove useful for us.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, we will be more likely to see innovative features out of a community around a product with a clean data structure than with communities around tools with less powerful data structures. These innovations may seem small at a cursory glance (like taking advantage of OS filesystem caching on fork switches); in the end they will empower our developers in deeper ways than can be seen at first (making new ways of working cheap).&lt;/p&gt;

&lt;h2 id=&quot;i-believe-that-community-matters-when-adopting-tools--especially-open-source&quot;&gt;I believe that community matters when adopting tools – especially open source&lt;/h2&gt;

&lt;p&gt;Community affects how well you can get your job done because community directly influences:&lt;/p&gt;

&lt;h3 id=&quot;when-the-tool-is-truly-revolutionary&quot;&gt;When the Tool is Truly Revolutionary&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Truly novel principles will attract thought leaders who will then provide both a strong and prominent voice in favor of a tool, and contribute mind-blowing innovative products and ideas around the core tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;when-the-community-includes-thought-leaders&quot;&gt;When the Community Includes Thought Leaders&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Innovation will follow the thought leaders.&lt;/li&gt;
  &lt;li&gt;Imitation will follow the innovation.&lt;/li&gt;
  &lt;li&gt;Innovation around a core feature is more valuable than innovation around a glossy feature.&lt;/li&gt;
  &lt;li&gt;Thought leaders and Innovation will attract Early Adopters&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;community-includes-the-masses&quot;&gt;Community Includes The Masses&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;The number of free articles published on your topic, because that’s driven by the number of users&lt;/li&gt;
  &lt;li&gt;The number of paid resources (like books and screencasts) on your tool, because that’s driven by what the market will pay for&lt;/li&gt;
  &lt;li&gt;The probability that a new developer we hire will be familiar with a tool, because that’s driven by market share&lt;/li&gt;
  &lt;li&gt;The number and stability of paid support options for your tool, because that’s again driven by what the market will pay for&lt;/li&gt;
&lt;/ul&gt;

</description>
        <pubDate>Mon, 11 Oct 2010 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Life at the End of the Tunnel</title>
        <link>http://timshadel.com/news/life-at-the-end-of-the-tunnel.html</link>
        <guid isPermaLink="true">http://timshadel.com/news/life-at-the-end-of-the-tunnel.html</guid>
        <description>&lt;p&gt;A couple months back I had a job change that took me out of state and brought my family back to where many of our extended family members live. We’ve been staying with my gracious in-laws for that time, looking for a place of our own. It looks like everything’s likely to go through at this point, and I’m optimistic that we may yet have all our stuff moved up and be able to establish familiar routines again.&lt;/p&gt;

&lt;p&gt;That’s all to say that I’m hoping to have more time for blogging in the coming weeks. I’ve got some good stuff to share on a number of topics. Cya.&lt;/p&gt;
</description>
        <pubDate>Tue, 31 Mar 2009 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>How Do I Love Thee?</title>
        <link>http://timshadel.com/news/how-do-i-love-thee.html</link>
        <guid isPermaLink="true">http://timshadel.com/news/how-do-i-love-thee.html</guid>
        <description>&lt;p&gt;Today a confluence of dissimilar events brought me to this post. A decade ago, today, I asked my sweet wife to marry me. I must have tricked her well, because she consented. We’ll be celebrating tonight, and I think of all the hard work it’s taken on both our parts to come to this place. As we’ve worked through it all, we’ve marveled together at the movies or TV shows that depict married couples not long into marriage, and the first time something tough comes up someone asks, “Do you think he wants out?” The answer often follows, “Probably. It’d be best, right?” &lt;a href=&quot;http://en.wikipedia.org/wiki/Marley_&amp;amp;_Me_(film)&quot;&gt;Marley &amp;amp; Me&lt;/a&gt; was a notable exception. The question was asked but answered with something akin to, “No. Marriage takes work.”&lt;/p&gt;

&lt;p&gt;And today I discovered that &lt;a href=&quot;http://lds.org&quot;&gt;my Church&lt;/a&gt; started a YouTube channel: &lt;a href=&quot;http://www.youtube.com/user/MormonMessages&quot;&gt;Mormon Messages&lt;/a&gt;. Moments ago they &lt;a href=&quot;http://www.youtube.com/watch?v=eM3mlgLAlMs&quot;&gt;posted something appropriate&lt;/a&gt; for Valentine’s day week, and for the decision and ensuing hard work, sacrifice, and love that my wife and I commemorate today. &lt;a href=&quot;http://newsroom.lds.org/ldsnewsroom/eng/background-information/leader-biographies/elder-jeffrey-r-holland&quot;&gt;Jeffrey R. Holland&lt;/a&gt;, an apostle today like Paul of old, takes a moment to talk about love.&lt;/p&gt;

&lt;p style=&quot;width:100%; text-align: center&quot;&gt;
&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;How true it is. Love takes work. Stephen R. Covey (also a Mormon) recounts in his book, 7 Habits of Highly Effective People, about the time he was approached by a man saying he had fallen out of love with his wife and wondered what to do about it. Covey replied, “Love her.” After a few rounds of this, Covey explained that love is a verb.&lt;/p&gt;

&lt;p&gt;Marriage is harder than any programming or design work I’ve ever undertaken, harder than any HR problem I’ve confronted as a manager. And when, after great effort, the children we dearly love came to us, the time we had to be together shrank dramatically: marriage took the same effort but was packed into 10% of the space it had before. That was harder.&lt;/p&gt;

&lt;p&gt;Nothing is sweeter than the rewards of hard work to build a good marriage and a good family. That work is often never seen, nor spoken about in public. It doesn’t win professional prestige or solve business profitability. It often doesn’t do much that’s visible to your peers, but nothing is sweeter than seeing a marriage relationship that’s been strengthened through work. Nothing more satisfying than developing together the skills to work through disagreements or resolve a number of small misunderstandings that suddenly get noticed together. Nothing more fun than having a whole series of inside jokes built both on the wonderful times and on your shared reflection on experience as a young and naive couple. Nothing more sweet than sharing a look of profound, shared feeling of delight as you gaze at a sleeping child after months of wrangling together with how to get them to go to bed while maintaining your cool, much less on time. Nothing like the feeling her hand touch yours and know the softness and caring in the act because you’ve experienced it throughout all kinds of weather and held to it.&lt;/p&gt;

&lt;p&gt;Nothing is so hard. In nothing have I felt so truly inadequate, or grown so much. Nothing has brought so much joy.&lt;/p&gt;

&lt;p&gt;And to my sweet Jennifer: thank you for agreeing 10 years ago to go on this lifelong journey with me. May it truly last forever. How do I love thee? Let me count the ways…&lt;/p&gt;

</description>
        <pubDate>Wed, 11 Feb 2009 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Making ‘Reply’ Do the Right Thing</title>
        <link>http://timshadel.com/craftsmanship/making-reply-do-the-right-thing.html</link>
        <guid isPermaLink="true">http://timshadel.com/craftsmanship/making-reply-do-the-right-thing.html</guid>
        <description>&lt;p&gt;This morning I got an email from Backpack, telling me that my business partner added a new page with some meeting minutes from our late night conversation the other day. I clicked the link, reviewed the page, and quickly rushed off a reply to his email saying that it looked good.&lt;/p&gt;

&lt;p&gt;Then I noticed it. It wasn’t &lt;em&gt;his&lt;/em&gt; email — it was sent by the Backpack system itself, not my friend. I rushed to my Sent Items, and found an email addressed to him. I was really surprised. I had lost context, focused on the author of the page instead of the email, wanted to respond about the content of the page, and the crew at 37signals just made the right thing happen automatically.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Notice what they didn’t do. They didn’t make me “Click here to respond to the author.” They didn’t invent a kludgey discussion area on Backpack for talking about the page content. And they didn’t just throw my email in the bit bucket because I hit Reply on a system generated message. They made things just work when my human habit of &lt;em&gt;hitting-Reply-to-talk-to-somebody-that-wrote-something-to-me&lt;/em&gt; kicked in.&lt;/p&gt;

&lt;p&gt;Two other nice things they did: gave the email author the simple name of &lt;em&gt;Backpack&lt;/em&gt;, and used an email address of &lt;code class=&quot;highlighter-rouge&quot;&gt;system at backpackit dot com&lt;/code&gt; that didn’t try to tell me not to actually use my email program to, you know, talk to people. I don’t know where the system address goes or how it’s responded to, and maybe other system emails are set to reply to that address. I’m guessing, though, that their example of great finish work on a system is carried throughout most of their other emails. It’s a humanized response that gives the system its polish.&lt;/p&gt;

&lt;p&gt;What emails is your system sending out. If someone were to hit Reply, who should get that email. If you immediately say, “No one” then think about if that recipient came to your office or picked up the phone, who would they need to talk to &lt;em&gt;so that they were helped properly&lt;/em&gt;. Is it Support? Is it their manager? Is it the VP of Marketing? Make the email go there. Make sure your customers need for human communication is fulfilled effortlessly and without thought or extra action. They will sing your praises.&lt;/p&gt;
</description>
        <pubDate>Thu, 08 Jan 2009 00:00:00 +0000</pubDate>
      </item>
    
      <item>
        <title>Craft Personas with a Template</title>
        <link>http://timshadel.com/how-to/craft-personas-with-a-template.html</link>
        <guid isPermaLink="true">http://timshadel.com/how-to/craft-personas-with-a-template.html</guid>
        <description>&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/Personas&quot;&gt;Personas&lt;/a&gt; help focus your work on the needs of real-ish users. In most places I’ve been, I’ve seen that over time the customer kind of morphs into a gelatinous mass of jumbled memory as contact with the actual end user is replaced by a marketing proxy. It’s a common experience, and there’s ways to reinvigorate your bowl full of jelly into something resembling actual users again.&lt;/p&gt;

&lt;p&gt;Last summer I attended &lt;a href=&quot;http://www.nofluffjuststuff.com/conference/speaker/david_hussman.html&quot;&gt;David Hussman&lt;/a&gt;‘s Agile Product Planning: Building Strong Backlogs session at the &lt;a href=&quot;http://www.agileitx.com/conference/reston/2008/06/index.html&quot;&gt;Agile It! Experience 2008&lt;/a&gt; in Reston. One thing that stuck with me was his goofy graphics of personas, and their alliterative names. Among many things, he talked about smells that creep into your planning process and how these usually indicated a loss of focus on the user. Smells like refactoring or engineering stories becoming common place instead of rare, and people talking about a “thing to do that takes time” instead of telling stories about how this work will help someone.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;He went into lots more detail, talking through the anatomy of a story, how to avoid letting the structure become so rote that it’s not doing its job, making stories testable, and pushing you to question the team if they think stories are hard to tell for a piece of work. The main piece I’ve latched onto lately, in hopes that it can help drive out some of the smell and impact the others, is his way of writing up personas. I’ll describe the finished product first and then come back to how they might be constructed. Near the end I’ve attached the template I made for Apple’s Pages program in iWork ’08.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2009/01/3171043037_282b9c105d.jpg&quot; alt=&quot;Persona picture&quot; style=&quot;float: left; padding-right: 5px; padding-bottom: 5px&quot; /&gt;First, use a color picture and print the persona pages in color. A picture of a real human being does amazingly subtle things to how you view interactions with data. Just ask anyone that uses Apple Mail and sees the contact picture on the email as they read it. It creates an &lt;a href=&quot;http://www.jnd.org/dn.mss/personas_empath.html&quot; title=&quot;Ad-Hoc Personas &amp;amp; Empathetic Focus by Don Norman&quot;&gt;empathic reaction &lt;/a&gt;that just can’t be done with text alone. Do it. A few minutes on the &lt;a href=&quot;http://search.creativecommons.org/&quot;&gt;Creative Commons search&lt;/a&gt; will make it easy.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2009/01/3171881872_21ab27c25c.jpg&quot; alt=&quot;Persona name&quot; style=&quot;float: right; padding-right: 5px; padding-bottom: 5px&quot; /&gt; Next, make sure each persona has a name. David Hussman really advocated using a name that has alliteration as a simple way to remember who’s who. I try to find a name that’s both fun and realistic (search for &lt;a href=&quot;http://www.google.com/search?hl=en&amp;amp;rls=en-us&amp;amp;q=chinese+baby+girl+names&quot;&gt;Chinese baby girl names&lt;/a&gt; or &lt;a href=&quot;http://www.google.com/search?hl=en&amp;amp;rls=en-us&amp;amp;q=tongan+baby+boy+names&quot;&gt;Tongan baby boy names&lt;/a&gt; if you need some help with modeling a global user base). The name ends up feeling like “William the Conqueror” or “Fredric the Shy” when you’re done because you have a real name and a tiny window into the personality.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2009/01/3171073837_fc8b019e1d.jpg&quot; alt=&quot;Persona description&quot; style=&quot;float: left; padding-right: 5px; padding-bottom: 5px&quot; /&gt; Description is key in my book. David’s examples used bullet points. I chose prose instead to get the feel of actually getting to know someone. Think of yourself as the announcer on some reality TV show if you can’t get into the swing of things beyond a couple bullets. Knowing that “Damion the Data Admin” loves to come into work early so he can go skiing every afternoon from November to March may seem useless at first. But when you realize that knowing seemingly innocuous trivia helps you recognize that if you add a feature that requires Damion to physically click OK 4 times over 90 minutes every day at 5pm, he’s gonna not like you or your silly software. Don’t overdo it, but do add enough personality to remember that your software is not the center of this person’s life. They’ll drop it like a rock for chatting with a coworker, attending a kid’s soccer game, or jumping up to salute the boss. Again, this is to provide some low empathic response for the group you’re talking about.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2009/01/3171073809_8ce65dc596.jpg&quot; alt=&quot;Persona values&quot; style=&quot;float: right; padding-right: 5px; padding-bottom: 5px&quot; /&gt; After your little two paragraph bio on your fabled persona, the next item is Values. I’ve found that I like David’s example of bullet points here. It seems natural to call out simple value statements in harmony with the background you’ve developed for this persona. To me, the values often give you ideas on how this persona would make tradeoff decisions, and it can be enlightening as an engineer to experience that from different angles (personas). An example bullet under the Values heading might be something like, “* Visible indications of task progress, since he works in this application infrequently and likes to know his cumulative time here has been well spent.”&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2009/01/3171903620_ec552b79ca.jpg&quot; alt=&quot;Persona key facts&quot; style=&quot;float: left; padding-right: 5px; padding-bottom: 5px&quot; /&gt; Finally, the Key Facts seem to trigger reminders about the general situation of the persona, or about the group this persona represents. “Limited computer access,” or “May be 80,000 Arthurs” are good examples. I try to find stuff that’s either not covered elsewhere, or mentioned but not highlighted. You don’t want people to just read your key facts as a summary instead of actually getting to know the persona, because that’d defeat the purpose.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2009/01/3171128567_abe440c2bc.jpg&quot; alt=&quot;Persona color change&quot; style=&quot;float: right; padding-right: 5px; padding-bottom: 5px&quot; /&gt; Feel free to grab my iWork persona template below and hack it up however you’d like. Drop it in your home folder in &lt;code class=&quot;highlighter-rouge&quot;&gt;Library/Application Support/iWork/Pages/Templates/My Templates/&lt;/code&gt; and it will appear in the My Templates pane of the Template Chooser. Whenever I make a new persona, I change the fill of the box below the picture to a color I pick out of the new photo. Next I go adjust the color of everything in the template to be that color (pick from the box, instead of the photo for consistency). Even the background box behind the Key Facts will work if you just use the same color (it’s opacity is less than 100%).&lt;/p&gt;

&lt;p style=&quot;clear: both&quot;&gt;
  I&amp;#8217;d love to hear about your use or abuse of personas in your planning process, and ways that you&amp;#8217;ve made it fun and practical to know your real customers.
&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://github.com/timshadel/persona-placeholder/tree&quot; title=&quot;GitHub Persona Placeholder Project&quot;&gt;&lt;img src=&quot;http://timshadel.com/wp-content/uploads/2009/01/3171034009_6cb6c21120.jpg&quot; alt=&quot;Persona preview&quot; /&gt;&lt;/a&gt;
&lt;a href=&quot;http://github.com/timshadel/persona-placeholder/tree&quot; title=&quot;GitHub Persona Placeholder Project&quot;&gt;Download iWork Pages Template&lt;/a&gt; from GitHub project.&lt;/p&gt;

</description>
        <pubDate>Mon, 05 Jan 2009 00:00:00 +0000</pubDate>
      </item>
    
  </channel>
</rss>
