<?xml version="1.0" encoding="UTF-8"?>
<!--Generated by Squarespace Site Server v5.9.1 (http://www.squarespace.com/) on Tue, 09 Feb 2010 10:20:38 GMT--><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>Play On</title><link>http://www.peeja.com/journal/</link><description></description><lastBuildDate>Tue, 08 Dec 2009 03:54:56 +0000</lastBuildDate><copyright></copyright><language>en-US</language><generator>Squarespace Site Server v5.9.1 (http://www.squarespace.com/)</generator><item><title>How to defeat Whole Disk Encryption and other in-memory-key schemes</title><dc:creator>Peter</dc:creator><pubDate>Tue, 08 Dec 2009 03:50:03 +0000</pubDate><link>http://www.peeja.com/journal/2009/12/7/how-to-defeat-whole-disk-encryption-and-other-in-memory-key.html</link><guid isPermaLink="false">339556:3591983:6015550</guid><description><![CDATA[<p><a href="http://www.wiebetech.com/products/HotPlug.php">Steal the computer</a> without ever turning off the power or letting the machine go to sleep.</p>

<p><span class="full-image-block ssNonEditable"><span><img src="http://www.peeja.com/storage/thumb.jpg?__SQUARESPACE_CACHEVERSION=1260244304148" alt=""/></span></span></p>

<p>Also useful for moving a Frogger game cabinet without losing your high scores.</p>

<p><span class="full-image-block ssNonEditable"><span><img src="http://www.peeja.com/storage/seinfeld_918_337x233_032320091259.jpg?__SQUARESPACE_CACHEVERSION=1260244455581" alt=""/></span></span></p>
]]></description><wfw:commentRss>http://www.peeja.com/journal/rss-comments-entry-6015550.xml</wfw:commentRss></item><item><title>Use the hell out of your Someday/Maybe lists.</title><dc:creator>Peter</dc:creator><pubDate>Sat, 01 Aug 2009 22:47:04 +0000</pubDate><link>http://www.peeja.com/journal/2009/8/1/use-the-hell-out-of-your-somedaymaybe-lists.html</link><guid isPermaLink="false">339556:3591983:4801334</guid><description><![CDATA[<p>I don&#8217;t think it&#8217;s advertised anymore, but Merlin Mann&#8217;s great <a href="http://www.43folders.com/" title="43 Folders | Time, Attention, and Creative Work">43 Folders</a> site has a companion <a href="http://groups.google.com/group/43Folders" title="43 Folders | Google Groups">Google Group</a>.  These days it doesn&#8217;t get much traffic.  I&#8217;d actually forgotten it existed until I saw <a href="http://groups.google.com/group/43Folders/browse_thread/thread/c5436531493abf3e" title="Getting back... - 43 Folders | Google Groups">this question</a> in my inbox.</p>

<p>My answer explains a small nugget of GTD wisdom I&#8217;ve been able to distill over the past few months, and I&#8217;d like to share it with you here.</p>

<hr />

<p>On Mon, Jul 20, 2009 at 2:20 PM, DerekS wrote:</p>

<blockquote>
  <p>I have been on and off the wagon several times with respect to GTD and
  have finally noticed that all the things I want/need to get to are
  just floating around and making my head spin.</p>
</blockquote>

<p>I go in cycles as well, and every time I get a little closer to
something truly maintainable.  Let me give you a tip from my latest
go-round:</p>

<p>Use the hell out of your Someday/Maybe lists.</p>

<p>Before you put something on an action or project list, ask yourself:
when I find myself in the context to take action on this, <strong>am I really
going to do it</strong>?  Do I really care?  Have I actually committed to doing
this, or is it just something which seems like I might want to do?  If
you&#8217;re not truly committing to doing it as soon as you&#8217;re in that
context, put it on your Someday/Maybe list.</p>

<p>I keep a few S/M lists:</p>

<ol>
<li><strong>Someday Soon</strong>: Things I&#8217;ve pretty much decided I&#8217;ll do, but I
haven&#8217;t decided to start working on yet.  I consult this weekly.</li>
<li><strong>Someday Perhaps</strong>: Things I&#8217;m not sure I&#8217;ll want to do, but which I
don&#8217;t want to forget about.  I consult this one weekly too, but with a
different mindset.</li>
<li><strong>40,000ft Options</strong>: Basically career paths which I might like to
shift to one day.  I don&#8217;t consult this one much, but it&#8217;s good to
have a place to put those ideas.</li>
<li><strong>Way Out There</strong>: Crazy ideas I&#8217;ll probably never do, but which,
again, I feel better for having written down.</li>
<li><strong>Movies to Watch, Books to Read, etc</strong>: a series of lists of media I&#8217;d
like to consume.  I consult these when I&#8217;m looking for a good book,
movie, etc.</li>
</ol>

<p>All this means that my project and action lists have no noise.
They&#8217;re all things that I&#8217;m ready to do at a moment&#8217;s notice.</p>

<p>For this to work, the <strong>Weekly Review</strong> is critical.  If you don&#8217;t trust
that you&#8217;ll see these things as often as you feel you need to see
them, you&#8217;ll instinctively put them somewhere where you will.  That
will probably be your action and project lists.  Once those become
cluttered with things you haven&#8217;t actually decided to do yet, you&#8217;ll
stop trusting them, and then you&#8217;ve got nothing.  I&#8217;ve been through
that cycle numerous times.</p>

<p>I used to put off my weekly reviews for all sorts of poor reasons.
Just schedule an hour or two every week at the same time and check
your lists for inconsistencies.  You don&#8217;t even have to think very
hard.  If you just read over your action, project, and S/M lists, your
brain will tell you when something&#8217;s in the wrong place, or out of
date.</p>

<p>You can get better at the Weekly Review over time, but only if you
actually do it.  It&#8217;s far more important to <em>do</em> it than to do it
<em>well</em>.</p>
]]></description><wfw:commentRss>http://www.peeja.com/journal/rss-comments-entry-4801334.xml</wfw:commentRss></item><item><title>I'm joining Pivotal Labs!</title><dc:creator>Peter</dc:creator><pubDate>Fri, 24 Jul 2009 15:46:48 +0000</pubDate><link>http://www.peeja.com/journal/2009/7/24/im-joining-pivotal-labs.html</link><guid isPermaLink="false">339556:3591983:4730975</guid><description><![CDATA[<p>I am elated to announce that as of Monday I will be joining Pivotal Labs!</p>

<p>If you don&#8217;t know, Pivotal Labs is an elite ninja squad of developers, trained in the art of Ekusupidō (also known as Extreme Programming).  Pivotal, based in San Francisco, is growing their new(-ish) NYC office, and I&#8217;m proud to be joining the wonderful group of Pivots who work there.</p>

<p>Yesterday was my last day at drop.io.  I worked there for just over a year, and it has been a wild and hugely valuable experience.  When I arrived at drop.io, fresh out of college, I really didn&#8217;t know what I was doing.  I <em>thought</em> I knew what I was doing, but I didn&#8217;t.  A year later, I know what it&#8217;s like to accidentally bring down a popular website and rush out a fix.  I know what it&#8217;s like to be clever with my code and confuse the hell out of my coworkers.  Most importantly, <em>now</em> I can (usually) recognize when I&#8217;m about to do something stupid, and decide not to.</p>

<p>I owe drop.io a huge thanks.  Thanks for taking on someone with so little experience, and thanks for letting me experiment while I found my dev-legs.</p>

<p>Yesterday, the team threw a little sendoff party for me.  There was pizza, beer, and stories aplenty.  Then Mike and Pete scurried off.  When they came back, they were holding these:</p>

<p><a href="http://www.flickr.com/photos/peeja/3752696998/" title="It's Class Reloading: The T-Shirt by Peeja, on Flickr"><img src="http://farm4.static.flickr.com/3423/3752696998_8ff6673e81.jpg" width="500" height="375" alt="It's Class Reloading: The T-Shirt" /></a></p>

<p>I&#8217;m bowled over, guys.  That is the best present ever.  Though, as someone pointed out, it raises the question: can you wear a shirt with your own face on it?</p>

<p>A big thank-you to everyone at drop.io.  I&#8217;ll see you on Twitter, I&#8217;ll see you on Foursquare, and hopefully I&#8217;ll see you at an upcoming Wet Sox game.</p>

<p>(Apologies if this post was a little inside whiffleball.)</p>
]]></description><wfw:commentRss>http://www.peeja.com/journal/rss-comments-entry-4730975.xml</wfw:commentRss></item><item><title>Where We Came From</title><dc:creator>Peter</dc:creator><pubDate>Thu, 11 Jun 2009 02:35:17 +0000</pubDate><link>http://www.peeja.com/journal/2009/6/11/where-we-came-from.html</link><guid isPermaLink="false">339556:3591983:4281212</guid><description><![CDATA[<p>I had many favorite books when I was growing up, but one has always stuck with me.  The book is <a href="http://www.amazon.com/gp/product/0064604179?ie=UTF8&amp;tag=peejacom-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0064604179">The Cartoon Guide to Computer Science</a><img src="http://www.assoc-amazon.com/e/ir?t=peejacom-20&amp;l=as2&amp;o=1&amp;a=0064604179" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> by the great Larry Gonick.  It traces the history of computer science and explains how logic gates work, why a computer subtracks by adding, and why sloths count in binary.  it&#8217;s as good as David Macaulay&#8217;s <a href="http://www.amazon.com/gp/product/0395938473?ie=UTF8&amp;tag=peejacom-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0395938473">The Way Things Work</a><img src="http://www.assoc-amazon.com/e/ir?t=peejacom-20&amp;l=as2&amp;o=1&amp;a=0395938473" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> which is, after all, the greatest book ever written.  (The Way Things Work rates slightly higher, on account of its sheer inexhaustibility.)</p>

<p>When I arrived at Bard College as a freshman, I wanted to study Computer Science History.  I had stories of Charles Babbage, Ada Lovelace, and Alan Turing bubbling in my mind.  I wanted to learn more about where it all came from.  What happy accidents and brilliant insanities had built on top of one another to construct our modern computational world?</p>

<p>No one would teach me the history of computer science, so I settled for what I could pick up on my own.  Soon I discovered the computational pioneers of the modern era.  I learned how Alan Kay created Objects; how his GUI at PARC inspired Steve Jobs and Apple to create the Macintosh, which in turn inspired Windows and set the standard for computer interfaces; how his Smalltalk inspired Objective-C and Ruby, which was also highly influenced by John McCarthy&#8217;s Lisp.  I learned how Linus Torvalds and Richard Stallman built the two great empires of Free Software, Linux and GNU, living in symbiosis, and leading the way for the Open-Source Movement.  I learned of giants, gods, and titans, and I learned that they were my ancestors.  And then I realized something:</p>

<p>These people are still <em>alive</em>.</p>

<p>This still boggles my mind.  These are great men and women of history, and they&#8217;re not dead yet.  We can still go ask them questions.  We can even work with them, learn directly from them.  How lucky we are to live in an age of such rapid change that our Great Old Ones are still among us!</p>

<p>May we young grasshoppers be wise enough to seek their wisdom.</p>

<hr />

<p><a href="http://www.coreyhaines.com/" title="Corey Haines">Corey Haines</a> is touring the country pairing with all sorts of great programmers.  As he&#8217;s travelled, he&#8217;s filmed a series called &#8220;Road Thoughts&#8221;.  In <a href="http://programmingtour.blogspot.com/2009/05/road-thoughts-history.html" title="On Being A Journeyman Software Craftsman: Road Thoughts - History">his latest entry</a>, Corey discusses the importance of learning and remembering our history.  I think he&#8217;s absolutely right.</p>

<p><object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=4930313&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=4930313&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object></p>
]]></description><wfw:commentRss>http://www.peeja.com/journal/rss-comments-entry-4281212.xml</wfw:commentRss></item><item><title>tracker_chat 2: Chat Harder.</title><dc:creator>Peter</dc:creator><pubDate>Tue, 09 Jun 2009 18:23:06 +0000</pubDate><link>http://www.peeja.com/journal/2009/6/9/tracker_chat-2-chat-harder.html</link><guid isPermaLink="false">339556:3591983:4242187</guid><description><![CDATA[<p>I&#8217;ve updated the <a href="http://peeja.squarespace.com/journal/2009/6/3/pivotal-tracker-dropio-chat-together-as-one.html" title="Pivotal Tracker &amp; drop.io chat, together as one.">tracker_chat</a> script.  Now you can:</p>

<ul>
<li>Drag a story to the chat.  Its URL will be added to the chat input box so you can say something about it.</li>
<li>Click a story URL someone has posted to the chat.  That story will be revealed in Tracker without opening a new page.</li>
</ul>

<p>Hopefully these changes will make it easier to discuss Tracker stories in chat.</p>

<p>To install tracker_chat, install <a href="https://addons.mozilla.org/en-US/firefox/addon/748">Greasemonkey</a> in your Firefox 3, and then click here: <a href="http://github.com/Peeja/tracker_hacks/raw/eb39d355979c072eeab0f4d952222515009f77f3/tracker_chat.user.js">Install tracker_chat</a></p>
]]></description><wfw:commentRss>http://www.peeja.com/journal/rss-comments-entry-4242187.xml</wfw:commentRss></item><item><title>Pivotal Tracker &amp; drop.io chat, together as one.</title><dc:creator>Peter</dc:creator><pubDate>Wed, 03 Jun 2009 22:17:16 +0000</pubDate><link>http://www.peeja.com/journal/2009/6/3/pivotal-tracker-dropio-chat-together-as-one.html</link><guid isPermaLink="false">339556:3591983:4179999</guid><description><![CDATA[<p>My Tracker has chat built in, and so can yours.</p>

<p>At drop.io, we&#8217;re in the process of moving from <a href="http://www.lighthouseapp.com/">Lighthouse</a> to <a href="http://www.pivotaltracker.com/">Pivotal Tracker</a>.  Lighthouse is great for storing bugs, for searching them, and for maintaing a threaded conversation on each one.  It works well for the open source development model.  That&#8217;s basically what we used to do.</p>

<p>Now we&#8217;re moving to an Agile model.  We create and deliver many small amounts of customer value, we work in an iteration-based rhythm, and we work together as a team, or at least we&#8217;re aware of what everyone else is working on.  Tracker is perfect for that workflow.  But this isn&#8217;t a post about how awesome Tracker is.  This is a post about how I made it a little more awesome.</p>

<p><a href="http://www.flickr.com/photos/peeja/3592921141/" title="tracker_chat by Peeja, on Flickr"><img src="http://farm4.static.flickr.com/3637/3592921141_21b3ca6c4a.jpg" width="500" height="265" alt="tracker_chat" /></a></p>

<p>We all sit in chat all day, and naturally we use drop.io as our chat service.  It works really well, because when it doesn&#8217;t, we fix it.  I usually keep it up on my laptop screen while I work on my external monitor.</p>

<p>But Tracker updates itself in real time, so it&#8217;s nice to keep it up all the time too.  So now I want to have <em>it</em> on my laptop screen.</p>

<p>Now I have both.</p>

<h3>Requirements</h3>

<ul>
<li>Firefox</li>
<li>Greasemonkey</li>
</ul>

<h3>To Install</h3>

<ol>
<li>Navigate to <a href="http://github.com/Peeja/tracker_hacks/raw/eb39d355979c072eeab0f4d952222515009f77f3/tracker_chat.user.js" title="tracker_chat.user.js">the script</a>.</li>
<li>If you haven&#8217;t created a drop to chat in, create one at <a href="http://drop.io/" title="simple private real-time sharing and collaboration by drop.io">drop.io</a>. (One click, no signup.)</li>
<li>Go to your Tracker project.</li>
<li>From the Views menu, choose &#8220;Chat&#8230;&#8221;.</li>
<li>Give it the name of your drop.</li>
<li>Enjoy!</li>
</ol>

<h3>GreaseKit</h3>

<p>Unfortunately, tracker_chat doesn&#8217;t work perfectly in GreaseKit.  The chat will appear in Tracker, but with the full chrome you&#8217;d see if you viewed the chat normally.  In Firefox/Greasemonkey, extraneous chrome is hidden to save as much real estate as possible.</p>

<h3>More Info</h3>

<p>Check it out on GitHub at <a href="http://github.com/Peeja/tracker_hacks">http://github.com/Peeja/tracker_hacks</a>.</p>
]]></description><wfw:commentRss>http://www.peeja.com/journal/rss-comments-entry-4179999.xml</wfw:commentRss></item><item><title>Harder, Better, Faster, Stronger</title><dc:creator>Peter</dc:creator><pubDate>Thu, 23 Apr 2009 03:28:35 +0000</pubDate><link>http://www.peeja.com/journal/2009/4/23/harder-better-faster-stronger.html</link><guid isPermaLink="false">339556:3591983:3772687</guid><description><![CDATA[<p>Today marks the end of the first week of Agility at drop.io!</p>

<p><em>One week earlier&#8230;</em></p>

<p>Every Tuesday we start the day with a full-team meeting which we call a scrum (though it&#8217;s not quite a real scrum meeting).  At last week&#8217;s scrum, Sam and Jacob introduced our new development practices:</p>

<ul>
<li>We operate in two-week cycles (or iterations).</li>
<li>There are four areas of development to work on.</li>
<li>Each cycle is dedicated to working on one of the four areas.</li>
<li>Stories are written on the board.</li>
<li>To claim a story, a developer puts their name next to it.</li>
<li>When a story is complete, it&#8217;s erased and put on a piece of paper, which is taped to the &#8220;Ready for Staging&#8221; area.</li>
<li>When a story is deployed to staging, it&#8217;s moved to &#8220;Staging&#8221;.</li>
<li>When everything in staging has passed QA, we can deploy to production.</li>
<li>When a story is deployed to production, it&#8217;s moved to the production wall.</li>
</ul>

<p>That&#8217;s about it.  Now there&#8217;s a lot about Agile that&#8217;s not here.  There&#8217;s no story estimation.  There&#8217;s no iteration planning.  Stories can be added mid-iteration (and often are).  The product owner role is almost non-existent.  The developers implement stories in the order they choose.</p>

<p>But it&#8217;s a start.  Even this much is a <em>huge</em> change for us, and a very welcome one.  It&#8217;ll be a while before we&#8217;re comfortable enough to wade further in, and I&#8217;m ok with that.  We&#8217;re learning every day about how to make this work.</p>

<p>We&#8217;ve included the most important element of Agile development, however: regular retrospectives.  As long as you review your process and your progress regularly (and honestly), it&#8217;s hard to go wrong.  Over the next few months I expect we&#8217;ll rapidly adopt even better practices for our team as we discover what those are.</p>

<p>Next week I&#8217;ll write up how our first retrospective goes.</p>
]]></description><wfw:commentRss>http://www.peeja.com/journal/rss-comments-entry-3772687.xml</wfw:commentRss></item><item><title>Abstract Classes, For Ruby: Abstraction</title><dc:creator>Peter</dc:creator><pubDate>Sun, 12 Apr 2009 22:42:15 +0000</pubDate><link>http://www.peeja.com/journal/2009/4/12/abstract-classes-for-ruby-abstraction.html</link><guid isPermaLink="false">339556:3591983:3628734</guid><description><![CDATA[<p>Let&#8217;s say you&#8217;ve got a class called <code>Car</code>.  There are two subclasses of <code>Car</code>: <code>Convertible</code> and <code>Sedan</code>.  And it turns out that all cars are either convertibles or sedans.  (Who knew?)  So really, there&#8217;s no reason that a car object wouldn&#8217;t be an instance of <code>Convertible</code> or <code>Sedan</code>, and in fact an object that&#8217;s a direct instance of <code>Car</code> itself won&#8217;t even work correctly.</p>

<pre><code>class Car
  def go_forward
    # ...
  end
end

class Convertible &lt; Car
  def door_count
    2
  end
end

class Sedan &lt; Car
  def door_count
    4
  end
end
</code></pre>

<p>How would you write <code>Car#doors</code>?  You wouldn&#8217;t, because unlike moving forward, that behavior isn&#8217;t shared across all cars.  <code>Car</code> is an abstract class: a class that should never be instantiated directly.</p>

<p>But what&#8217;s stopping us?  Nothing.  And that&#8217;s a problem.  So let&#8217;s fix it:</p>

<pre><code>$ sudo gem install abstraction
</code></pre>

<p>Then:</p>

<pre><code>require 'abstraction'

class Car
  abstract

  def go_forward
    # ...
  end
end

Car.new
#&gt; AbstractClassError: Car is an abstract class and cannot be instantiated
</code></pre>

<p>But:</p>

<pre><code>Convertible.new  # =&gt; #&lt;Convertible:0x8fdf4&gt;
</code></pre>

<p>Awesome.</p>

<h2>Awesome?  Why so awesome?</h2>

<p>Ok, let&#8217;s take it back a step.  You&#8217;ve got a <code>Car</code> class with no subclasses.  They haven&#8217;t been necessary, and you don&#8217;t want to add complexity you don&#8217;t need.  Good for you.</p>

<pre><code>class Car
  def go_forward
    # ...
  end
end
</code></pre>

<p>Cars go forward, and that&#8217;s about it.  Except, now some parts of the code want to know how many doors a car has.  Remember, that depends on the kind of car it is, so we&#8217;ll need <code>Car</code> to know about its type.  And since convertibles are pretty rare in your code, you have cars be sedans by default.</p>

<pre><code>class Car
  attr_reader :type

  def initialize(type=:sedan)
    @type = type
  end

  def door_count
    case type
    when :convertible
      2
    when :sedan
      4
    end
  end

  def go_forward
    # ...
  end
end
</code></pre>

<p>Pretty soon you realize its time to refactor this puppy.  You want a refactoring called <a href="http://www.refactoring.com/catalog/replaceTypeCodeWithSubclasses.html" title="Refactoring: Replace Type Code with Subclasses">Replace Type Code with Subclasses</a>.  What you end up with is the set of classes we saw at the beginning:</p>

<pre><code>class Car
  def go_forward
    # ...
  end
end

class Convertible &lt; Car
  def door_count
    2
  end
end

class Sedan &lt; Car
  def door_count
    4
  end
end
</code></pre>

<p><strong>The problem</strong> is that all of your tests are passing, but none of your code is using the subclasses yet.  You could probably grep or ack through your source to find all of the times you use <code>Car.new</code>; in fact, you should.  But you should still be <em>testing</em> that you&#8217;ve done it right.  Also, if <code>Car</code> is backed by an ORM, <em>it</em> might be creating <code>Car</code> objects for you.</p>

<p>But as we&#8217;ve seen, Abstraction clears that all up.  Just make the class abstract&#8230;</p>

<pre><code>class Car
  abstract

  def go_forward
    # ...
  end
end
</code></pre>

<p>&#8230;and watch your tests fail.  When they pass again, you&#8217;ve completed the refactoring.</p>

<h1>Abstract Methods</h1>

<p><em>(Warning: this section is a bit of a tease.)</em></p>

<p>Traditionally, abstract classes are found in strongly typed languages, where the compiler makes sure they&#8217;re never created by type checking.  In the Ruby world, the test suite is essentially our type checker.  No complier can statically prove that an abstract Ruby class will never be instantiated, but we can exercise the test suite and see if it ever happens.</p>

<p>Abstract classes usually have a way to notate abstract methods.  These are methods which are declared in the superclass, but don&#8217;t have an implementation there.  A concrete subclass has to implement all of the abstract methods.  Again, this is checked by the type checker.</p>

<p>We have an example of an abstract method above, it&#8217;s just not denoted in any way: <code>#door_count</code>.  Similar to the case of abstract classes, we can&#8217;t prove statically that abstract methods are implemented in the concrete subclasses.  We have to run the tests and see if they&#8217;re defined when they&#8217;re called.</p>

<p><strong>But</strong>: if they&#8217;re called and there&#8217;s no implementation, we&#8217;ll get a <code>NoMethodError</code> anyway.  The declaration of an abstract method in the superclass is really only useful to the type checker, to tell it that, for instance, any <code>Car</code> object has a <code>#door_count</code> method.  We don&#8217;t have a type checker.  So we don&#8217;t need to declare abstract methods.</p>

<h2>But wouldn&#8217;t it be useful?</h2>

<p>It would be, if it were meaningful.  The problem is: what does it mean to implement a method?  In Ruby you really can&#8217;t know whether a method is implemented until you send it the message and see if it raises a <code>NoMethodError</code>.  There&#8217;s no way to determine whether a class &#8220;implements&#8221; all of its superclasses abstract methods without making assumptions like that the class doesn&#8217;t use <code>method_missing</code> or that instances of the class won&#8217;t get their own singleton implementations.  And the nail in the coffin: there&#8217;s no time when a Ruby class is done being implemented, so there&#8217;s no time to check.</p>

<p>On the other hand, maybe there&#8217;s a way to make it useful.  If there is, it certainly belongs here, so drop me a line or just fork away.</p>

<h2>Where&#8217;s the Code?</h2>

<p>Grab the source from the <a href="http://github.com/Peeja/abstraction">GitHubs</a>.  Pull requests more than welcome.</p>
]]></description><wfw:commentRss>http://www.peeja.com/journal/rss-comments-entry-3628734.xml</wfw:commentRss></item><item><title>Pair Programming: The First Week</title><dc:creator>Peter</dc:creator><pubDate>Sat, 04 Apr 2009 15:39:34 +0000</pubDate><link>http://www.peeja.com/journal/2009/4/4/pair-programming-the-first-week.html</link><guid isPermaLink="false">339556:3591983:3555095</guid><description><![CDATA[<p>For years now I&#8217;ve heard about the benefits of pair programming.  Pair programming is like coding with the buddy system.  Instead of sitting at your own machine writing code by yourself, you and a colleague sit at the same box working together.  I&#8217;ve heard that it&#8217;s faster than solo programming.  I&#8217;ve heard that it produces fewer bugs.  And I&#8217;ve heard that it&#8217;s just more fun.  Last week I went to the <a href="http://phillyemergingtech.com/">Philly Emerging Tech for the Enterprise</a> conference, and I heard even more praise for pair programming.  We don&#8217;t do pair programming at drop.io, not out of dislike as much as inexperience.  We&#8217;ve never really tried it.</p>

<p>So I tried it.  <a href="http://twitter.com/ChrisRicca">Chris</a> sits next to me, and we often show each other what we&#8217;re working on, so pairing with him seemed natural.  It turned out he&#8217;d been curious too.  We started on Monday, and now it&#8217;s been a week.  So what have I found?</p>

<p><strong>It&#8217;s all true.</strong>  We blew through huge amounts of stuff.  When you&#8217;re working with a pair, you can&#8217;t check your email every five minutes, or read Twitter, or watch YouTube videos.  You stay on task.  If one person gets up to get some water from the cooler, the other person can keep going.  You catch all sorts of mistakes.  I found these usually weren&#8217;t things which would become bugs, but they would have given us weird failures and taken longer to track down if we didn&#8217;t catch them immediately, like typos or forgetting to change the name of a method in one place.</p>

<p>Most importantly, though, we talked.  When you&#8217;re working by yourself, it&#8217;s easy to just <em>code</em> and not think about how much time you&#8217;re taking to futz with a Rake task or implement a design pattern until— I&#8217;m late!  I&#8217;m late!  For a very important date!  And as your deadline whooshes past you wonder where all the time went.</p>

<p>Working with a pair was different.  We talked through everything as we did it, which meant we saw issues before went down rabbit holes.  I felt extremely <strong>effective</strong>.</p>

<p>But there&#8217;s something else they say about pair programming, and it&#8217;s true too.  It&#8217;s <strong>exhausting</strong>.  Remember, you&#8217;re working full-steam, no futzing.  It&#8217;s great while you&#8217;re doing it, but it&#8217;s easy to wear out.  Always take frequent breaks when you&#8217;re pairing.  You&#8217;ll still come out ahead, and—more importantly—you won&#8217;t keel over and die.</p>

<p>We also learned that some things don&#8217;t go well with pairing.  Chris, being primarily a front-end guy, does a lot of styling and design.  His CSS skills were useful in our pairing project where we touched the full stack from models to views.  However, he&#8217;s working on some other things which are <em>just</em> design.  Pairing there didn&#8217;t do much for us; it was mostly me watching him work.  Pairing seems to work better when there&#8217;s more logical thinking to do.</p>

<p>We also found that the driver/navigator approach to pairing didn&#8217;t work well for us.  <a href="http://www.coreyhaines.com/">Corey Haines</a> in his (awesome) talk at Philly ETE said he preferred to give each person their own keyboard and mouse.  That worked best for us too.  We could switch typers rapidly, without moving the keyboard around.</p>

<p>Pairing is a habit.  It is, I think, one of the Good Habits of Programming.  Like TDD, it feels weird at first, then helpful, and eventually necessary.  I can still code without a pair, just as I can code without tests, but why would I want to?</p>
]]></description><wfw:commentRss>http://www.peeja.com/journal/rss-comments-entry-3555095.xml</wfw:commentRss></item><item><title>Fullscreen Screen Sharing with Multiple Displays</title><dc:creator>Peter</dc:creator><pubDate>Sat, 07 Mar 2009 18:29:00 +0000</pubDate><link>http://www.peeja.com/journal/2009/3/7/fullscreen-screen-sharing-with-multiple-displays.html</link><guid isPermaLink="false">339556:3591983:3584131</guid><description><![CDATA[<p>At work, I have a MacBook hooked up to a 30&#8221; display.  I use the external display for most things and the MacBook&#8217;s LCD mostly for chat.  Today, I had to work from home.  When this happens, I have three options:</p>

<ol>
<li>Use Leopard&#8217;s Screen Sharing.app,</li>
<li>Use the screen sharing built into iChat, or</li>
<li>Use a normal VNC client.</li>
</ol>

<p>Screen Sharing.app lets me choose which screen I share.  That&#8217;s important, because I have the two screens.  In a normal VNC client or, curiously, in iChat (which shold know better), I&#8217;m forced to view both screens at once side-by-side, which makes them each quite tiny.</p>

<p>However, Screen Sharing.app lacks a full screen mode, which makes it hard to work in.  Since I&#8217;m working solely on the remote machine, I&#8217;d like to have it take over my display entirely.  iChat does full screen, as do many VNC clients, but they don&#8217;t let me choose a screen.</p>

<p>I&#8217;ve found an inelegant but passable solution.  Ian Handerson has written a nifty little SIMBL plugin called <a href="http://ianhenderson.org/megazoomer.html">Megazoomer</a>.  In any window, pressing Cmd-Return will &#8220;mega zoom&#8221; it to fill the screen.  Inside Screen Sharing.app the keystroke gets swallowed and sent to the remote machine, but you can still use the &#8220;Mega Zoom&#8221; menu item in the Window menu.</p>

<p>The best way to install it (you can ignore Ian&#8217;s instructions; they don&#8217;t work as well in Leopard) is to first install <a href="http://infinite-labs.net/plugsuit/">PlugSuit</a>, a handy preference pane for managing hacks like this.  Once it&#8217;s installed, open up PlugSuit in your System Preferences, and drag Megazoomer into the Extenders list.  Relaunch Screen Sharing, connect, and choose &#8220;Mega Zoom&#8221; from the Window menu.  Fullscreen glory.</p>

<p>You&#8217;ll notice that it&#8217;s not quite perfect, but it&#8217;s good enough for what I need.  For best results, adjust the remote display&#8217;s resolution to but as close to but not greater than your local resolution as possible.</p>
]]></description><wfw:commentRss>http://www.peeja.com/journal/rss-comments-entry-3584131.xml</wfw:commentRss></item></channel></rss>