<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0"><title>pseudofish</title><link href="http://pseudofish.com/" rel="alternate" /><id>http://pseudofish.com/</id><updated>2013-05-12T00:00:00+02:00</updated><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/Pseudofish" /><feedburner:info uri="pseudofish" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>-37.8626789658184</geo:lat><geo:long>144.972390718543</geo:long><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2FPseudofish" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FPseudofish" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2FPseudofish" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/Pseudofish" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2FPseudofish" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FPseudofish" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FPseudofish" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><entry><title>Rethinking how I handle email</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/uYbooTTNHs4/rethinking-how-i-handle-email.html" rel="alternate" /><updated>2013-05-12T00:00:00+02:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2013-05-12:rethinking-how-i-handle-email.html</id><content type="html">&lt;p&gt;Email started to take too long, so I recently changed my&amp;nbsp;approach.&lt;/p&gt;
&lt;p&gt;At work, we try to avoid unbounded queues. In a distributed service
architecture, they can be toxic and swamp otherwise well behaving&amp;nbsp;services.&lt;/p&gt;
&lt;p&gt;Email had become an unbounded queue. It kept piling up and swamping my
day. Time for a&amp;nbsp;change.&lt;/p&gt;
&lt;h3&gt;My new&amp;nbsp;process&lt;/h3&gt;
&lt;p&gt;I adapted
&lt;a href="http://www.manager-tools.com/2013/03/email-three-times-a-day-part-1"&gt;the&lt;/a&gt;
&lt;a href="http://www.manager-tools.com/2013/03/email-three-times-a-day-part-2"&gt;recommendations&lt;/a&gt;
from Manager Tools, and I now follow these&amp;nbsp;guidelines:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Schedule 30mins in the morning for&amp;nbsp;email.&lt;/li&gt;
&lt;li&gt;No more than three time periods of up to 30mins during a day for&amp;nbsp;email.&lt;/li&gt;
&lt;li&gt;If I start processing email, I must finish (empty&amp;nbsp;&lt;span class="caps"&gt;INBOX&lt;/span&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The key for me has been pushing myself to finish if I start. This means that a
spare five minutes cannot be spent &lt;em&gt;doing email&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;For things that I need to do, either I book time in my calendar or put an
entry in my &lt;a href="http://culturedcode.com/things/"&gt;task list&lt;/a&gt;, possibly with a&amp;nbsp;reminder.&lt;/p&gt;
&lt;p&gt;When I end up with something that I want to come back to later, I&amp;#8217;ll create a
task to refer back to it, and park the email in a &amp;#8220;Follow-up&amp;#8221;&amp;nbsp;folder.&lt;/p&gt;
&lt;p&gt;For random notes to self, I now add a task. Previously, I was cluttering
my inbox and compounding my mail&amp;nbsp;problem.&lt;/p&gt;
&lt;p&gt;I also switched to using &lt;a href="http://www.instapaper.com/"&gt;Instapaper&lt;/a&gt; for saving
articles from Twitter, also reducing emails to&amp;nbsp;myself.&lt;/p&gt;
&lt;h3&gt;Results&lt;/h3&gt;
&lt;p&gt;The last two weeks were a big&amp;nbsp;improvement.&lt;/p&gt;
&lt;p&gt;I am feeling less stressed by email, and more focused on important
activites. I also feel like I have more time to handle unexpected events and
to chat with&amp;nbsp;colleagues.&lt;/p&gt;
&lt;p&gt;I still catch myself checking email on occasion, however often my inbox is
empty, so I&amp;#8217;m slowly weaning myself of the&amp;nbsp;habit.&lt;/p&gt;
&lt;p&gt;For personal email accounts, I&amp;#8217;m using a similar approach, although with a
lower frequency of&amp;nbsp;checking.&lt;/p&gt;
&lt;p&gt;For my phone, I will occasionally check email there, and am a bit more relaxed
about the process. I also set all mail applications to only check mail when
manually&amp;nbsp;asked.&lt;/p&gt;
&lt;h3&gt;Measuring email&amp;nbsp;volume&lt;/h3&gt;
&lt;p&gt;Below is a chart of the email volume over the last two years for my work
account. I was curious how much email I was receiving, and how much I&amp;nbsp;sent.&lt;/p&gt;
&lt;p&gt;For the last few months, I received around 3 times the number of emails as the
same period last year. This is a factor of being involved in more projects,
and the growth of the company. November last year was during a major project,
and spiked in the number of emails I&amp;nbsp;received.&lt;/p&gt;
&lt;p&gt;I was surprised to find that I still send the same number of emails (~10-15
per&amp;nbsp;day).&lt;/p&gt;
&lt;p&gt;&lt;img alt="Email volume" src="http://pseudofish.com/static/images/email-volume.png" /&gt;&lt;/p&gt;
&lt;p&gt;The chart was generated via the &lt;span class="caps"&gt;IMAP&lt;/span&gt; interface to Gmail, and this Python&amp;nbsp;script:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="c"&gt;#!/usr/bin/env python&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;imaplib&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;count_of_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mailbox&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;span class="caps"&gt;INBOX&lt;/span&gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mailbox_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;search&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;r&amp;#39;(X-&lt;span class="caps"&gt;GM&lt;/span&gt;-&lt;span class="caps"&gt;RAW&lt;/span&gt; &amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;)&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email_ids&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;mailbox_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;[Gmail]/All Mail&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;passwd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;user@example.com&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;secret&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;M&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;imaplib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IMAP4_SSL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;imap.gmail.com&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;993&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;passwd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Date,All Mail,Sent,Received&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2012&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2013&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;xrange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;date_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;after: &lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;/1 before:&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;/31&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;all_mail_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count_of_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;date_query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mailbox_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;sent_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; from:&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;date_query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;sent_mail_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count_of_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sent_query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mailbox_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;received_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; to:&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;date_query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;received_mail_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;count_of_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;received_query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mailbox_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;/1, &lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="si"&gt;%d&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                       &lt;span class="n"&gt;all_mail_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                       &lt;span class="n"&gt;sent_mail_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                       &lt;span class="n"&gt;received_mail_count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The tricky part was finding a way to pass the X-&lt;span class="caps"&gt;GM&lt;/span&gt;-&lt;span class="caps"&gt;RAW&lt;/span&gt; parameter through to
&lt;span class="caps"&gt;IMAP&lt;/span&gt; to enable Gmail
&lt;a href="https://developers.google.com/google-apps/gmail/imap_extensions#extension_of_the_search_command_x-gm-raw"&gt;search criteria&lt;/a&gt;. This
allows you to use the same search expressions as from within&amp;nbsp;Gmail.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=uYbooTTNHs4:-IReQbuQwXY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=uYbooTTNHs4:-IReQbuQwXY:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/uYbooTTNHs4" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/rethinking-how-i-handle-email.html</feedburner:origLink></entry><entry><title>Using deft mode for notes in Emacs</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/0WfMQCZ_RH8/using-deft-mode-for-notes-in-emacs.html" rel="alternate" /><updated>2013-03-14T00:00:00+01:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2013-03-14:using-deft-mode-for-notes-in-emacs.html</id><content type="html">&lt;p&gt;&lt;a href="http://jblevins.org/projects/deft/"&gt;Deft&lt;/a&gt; mode is one of my favorite
discoveries of &lt;a href="http://www.gnu.org/software/emacs/"&gt;emacs&lt;/a&gt;, especially when
combined with the magic of &lt;a href="http://orgmode.org/"&gt;org-mode&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I use the combination of both deft and org-mode almost every day. If I&amp;#8217;m doing
an interview, taking notes in a meeting, keeping a personal backlog or ideas
for a project, then this is what I&amp;#8217;m&amp;nbsp;using.&lt;/p&gt;
&lt;p&gt;Deft solves the problem of where to put text files. Org-mode structures what
goes into&amp;nbsp;them.&lt;/p&gt;
&lt;p&gt;Deft can be installed via emacs packaging. I configure it like&amp;nbsp;this:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;require&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;deft&lt;/span&gt; &lt;span class="n"&gt;nil&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;noerror&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;setq&lt;/span&gt;
     &lt;span class="n"&gt;deft&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;extension&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;org&amp;quot;&lt;/span&gt;
     &lt;span class="n"&gt;deft&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;~/Dropbox/Notes/&amp;quot;&lt;/span&gt;
     &lt;span class="n"&gt;deft&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;I put the default folder within my Dropbox folder. This ensures notes are
backed up and available on any computer where I&amp;#8217;m using Dropbox and&amp;nbsp;emacs.&lt;/p&gt;
&lt;p&gt;Once in deft mode (&lt;code&gt;M-x deft&lt;/code&gt;):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;RET&lt;/code&gt; &amp;#8212; open the current&amp;nbsp;file&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-c C-n / C-RET&lt;/code&gt; &amp;#8212; create a new file (auto&amp;nbsp;named)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-c RET&lt;/code&gt; &amp;#8212; create a new file (prompt for&amp;nbsp;name)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-c C-r&lt;/code&gt; &amp;#8212; rename a&amp;nbsp;file&lt;/li&gt;
&lt;li&gt;&lt;code&gt;C-c C-d&lt;/code&gt; &amp;#8212; delete a&amp;nbsp;file&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To search for a particular file, just start typing and the results are
filtered in the same&amp;nbsp;view.&lt;/p&gt;
&lt;p&gt;For me, this has been near perfect for quick note taking. My current notes
folder holds over 150 org files and is still fast to&amp;nbsp;search.&lt;/p&gt;
&lt;p&gt;When sharing notes from meetings with others, I use org-mode&amp;#8217;s export feature
(&lt;code&gt;C-c C-e A&lt;/code&gt;), then highlight the part I want, and send it to the clipboard (&lt;code&gt;M-|
pbcopy&lt;/code&gt;) to paste into&amp;nbsp;email.&lt;/p&gt;
&lt;p&gt;Getting a solid system for note taking in emacs has helped with how often I
use the same text editor. This was also part of my motivation of migrating my
blog to text files (although markdown&amp;nbsp;formatted).&lt;/p&gt;
&lt;h2&gt;Additional&amp;nbsp;tips&lt;/h2&gt;
&lt;p&gt;To launch emacs from the command line with deft mode open, I set the following&amp;nbsp;alias:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;emacs --eval &amp;#39;(deft)&amp;#39;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Often I have similar formats for things like notes, minutes or interviews. To
avoid lots of typing, I use
&lt;a href="http://capitaomorte.github.io/yasnippet/"&gt;yasnippet&lt;/a&gt; to create&amp;nbsp;templates.&lt;/p&gt;
&lt;p&gt;For some examples, see my
&lt;a href="https://github.com/gmwils/dotfiles/tree/master/emacs.d/snippets/org-mode"&gt;dotfiles&lt;/a&gt;.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=0WfMQCZ_RH8:bv-CaVdvCWw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=0WfMQCZ_RH8:bv-CaVdvCWw:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/0WfMQCZ_RH8" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/using-deft-mode-for-notes-in-emacs.html</feedburner:origLink></entry><entry><title>Scandinavian Startups</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/wpBS7hNTu5o/scandinavian-startups.html" rel="alternate" /><updated>2013-02-21T00:00:00+01:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2013-02-21:scandinavian-startups.html</id><content type="html">&lt;p&gt;There is something in the water up here. The economy seems to be going well,
and the press seems to have taken&amp;nbsp;notice.&lt;/p&gt;
&lt;p&gt;An
&lt;a href="http://www.usatoday.com/story/tech/2013/02/16/klarna-spotify-mysql-king-dice-izettle/1923609/"&gt;example&lt;/a&gt;
from &lt;span class="caps"&gt;USA&lt;/span&gt;&amp;nbsp;Today:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If music service Spotify landed Stockholm on the high-tech map, companies
 such as Klarna underscore its growing&amp;nbsp;influence.&lt;/p&gt;
&lt;p&gt;In the first quarter of 2012, Sweden took in almost 20% of all venture
 capital invested in the European Union, trailing only&amp;nbsp;Germany&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And Pando Daily on
&lt;a href="http://pandodaily.com/2012/11/20/why-tiny-stockholm-has-the-most-stunning-startup-ecosystem-since-tel-aviv/"&gt;Stockholm&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Thanks to Klarna, Spotify, Rebtel, and King.com, among others, Stockholm has
a longer history of tech successes and more big-dollar exits than its German
rival&amp;nbsp;[Berlin].&lt;/p&gt;
&lt;p&gt;For instance, the Nordic region as a whole — which still represents a
much smaller population than Germany — accounted for about 6.5 percent of
the world’s billion-dollar exits from 2005 to 2012, according to statistics
provided by Stockholm-based venture capital firm&amp;nbsp;Creandum.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There is still room to grow, as European startups in general are
&lt;a href="http://thenextweb.com/insider/2013/02/16/european-startups-need-to-be-celebrated-for-success/"&gt;undervalued&lt;/a&gt;
compared to the&amp;nbsp;&lt;span class="caps"&gt;US&lt;/span&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Listed European technology firms valued at more than $100 million are on
average 32 percent cheaper than their North American peers. Bloomberg says
they trade at an average ratio of 15 times earnings compared with 22 times
earnings in the &lt;span class="caps"&gt;US&lt;/span&gt; and&amp;nbsp;Canada.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The Economist goes into depth on in their special report on
&lt;a href="http://www.economist.com/printedition/2013-02-02"&gt;The Nordic Lights&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Finland has become much more market- and entrepreneur-friendly. It has
produced an impressive number of start-ups, including 300 founded by former
Nokia&amp;nbsp;employees.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Nordic countries have not only largely escaped the economic problems that
are convulsing the Mediterranean world; they have also largely escaped the
social ills that plague&amp;nbsp;America.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I feel very lucky to have worked for a number of Nordic companies, and to
continue my Scandinavian adventure with Spotify here in&amp;nbsp;Stockholm.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=wpBS7hNTu5o:PtUnHof_0wM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=wpBS7hNTu5o:PtUnHof_0wM:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/wpBS7hNTu5o" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/scandinavian-startups.html</feedburner:origLink></entry><entry><title>New Blog</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/CvDq-4srzZw/new-blog.html" rel="alternate" /><updated>2013-02-10T00:00:00+01:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2013-02-10:new-blog.html</id><content type="html">&lt;p&gt;If things went well, this post will be from my new&amp;nbsp;blog.&lt;/p&gt;
&lt;p&gt;I migrated my existing blog across to use
&lt;a href="http://docs.getpelican.com/"&gt;Pelican&lt;/a&gt;, a static site generator written in
Python. This is part of attempting to use emacs &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; python for as much of my
workflow as&amp;nbsp;possible.&lt;/p&gt;
&lt;p&gt;During the migration, all the code and formatting were cleaned up, so it
should be easy to change. Previously, all the content was in a Wordpress
database, and not so easy to&amp;nbsp;transform.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not sure how attached I&amp;#8217;ll be to Markdown. I am contemplating adding
&lt;a href="http://orgmode.org/"&gt;org-mode&lt;/a&gt; support to Pelican, as I use it for most other&amp;nbsp;notetaking.&lt;/p&gt;
&lt;p&gt;You may notice some duplicate articles via &lt;span class="caps"&gt;RSS&lt;/span&gt;. This is unfortunately due to
changing the &lt;span class="caps"&gt;URL&lt;/span&gt;&amp;nbsp;scheme.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=CvDq-4srzZw:ANhOHOm-Jn4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=CvDq-4srzZw:ANhOHOm-Jn4:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/CvDq-4srzZw" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/new-blog.html</feedburner:origLink></entry><entry><title>Postgres database migrations with Python</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/DKzL5rTzo7s/postgres-database-migrations-with-python.html" rel="alternate" /><updated>2012-11-18T02:41:00+01:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2012-11-18:postgres-database-migrations-with-python.html</id><content type="html">&lt;p&gt;If you need to setup database migrations that work both locally and on
&lt;a href="https://devcenter.heroku.com/articles/heroku-postgresql"&gt;Heroku&lt;/a&gt; in Python, these steps may be&amp;nbsp;helpful.&lt;/p&gt;
&lt;p&gt;For a recent project, I wanted to be able to manage the database schema.
I&amp;#8217;m not using an &lt;span class="caps"&gt;ORM&lt;/span&gt;, however the migration features in &lt;a href="https://sqlalchemy-migrate.readthedocs.org/en/v0.7.2/versioning.html"&gt;SQLAlchemy&lt;/a&gt;
turn out to be quite&amp;nbsp;useful.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install the SQLAlchemy migration package, by adding the following to&amp;nbsp;requirements.txt.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="c"&gt;# Migrations&lt;/span&gt;
&lt;span class="n"&gt;sqlalchemy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;migrate&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;and&amp;nbsp;update:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;requirements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;txt&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a repository for database&amp;nbsp;migrations&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;migrate&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Cihui&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This creates a directory &lt;code&gt;db/&lt;/code&gt; where the code and migrations will&amp;nbsp;reside.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update the migrate script to use Heroku &lt;span class="caps"&gt;DB&lt;/span&gt;&amp;nbsp;url&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="c"&gt;#!/usr/bin/env python&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;migrate.versioning.shell&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;db_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;DATABASE_URL&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;postgresql://localhost:5432/cihui&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;db_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db_url&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;postgres:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;postgresql:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;db_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;debug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;False&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;db&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This should allow you to run migrations locally or on Heroku. There
was a warning message on Heroku for the url starting with postgres
rather than postgresql, thus the &lt;code&gt;replace&lt;/code&gt; line.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Update&amp;nbsp;Procfile&lt;/p&gt;
&lt;p&gt;This sets up a few useful targets to run on Heroku and locally using
&lt;a href="http://ddollar.github.com/foreman/"&gt;foreman&lt;/a&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;db_init&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;py&lt;/span&gt; &lt;span class="n"&gt;version_control&lt;/span&gt;
&lt;span class="n"&gt;db_version&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;  &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;py&lt;/span&gt; &lt;span class="n"&gt;db_version&lt;/span&gt;
&lt;span class="n"&gt;migrate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;py&lt;/span&gt; &lt;span class="n"&gt;upgrade&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To migrate&amp;nbsp;locally&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;foreman&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;init_db&lt;/span&gt; &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="n"&gt;foreman&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;migrate&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To run on&amp;nbsp;Heroku&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;heroku&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;db_init&lt;/span&gt;
&lt;span class="n"&gt;heroku&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;migrate&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Write migrations as&amp;nbsp;&lt;span class="caps"&gt;SQL&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I prefer to manually write the migrations, and SQLAlchemy has great
support for this. Refer to their docs for &lt;a href="https://sqlalchemy-migrate.readthedocs.org/en/v0.7.2/versioning.html#writings-sql-scripts"&gt;details&lt;/a&gt;.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="n"&gt;script_sql&lt;/span&gt; &lt;span class="n"&gt;postgresql&lt;/span&gt; &lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This generates an upgrade and downgrade sql script in &lt;code&gt;db/versions&lt;/code&gt;
with an appropriate version&amp;nbsp;number.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Test the&amp;nbsp;migration:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;python&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;manage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;py&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Runs upgrade and then downgrade on a single&amp;nbsp;version.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;span class="caps"&gt;DB&lt;/span&gt; access to&amp;nbsp;Heroku&lt;/p&gt;
&lt;p&gt;Console access is available&amp;nbsp;via:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;heroku&lt;/span&gt; &lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;psql&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Useful for checking specific values or fixing broken&amp;nbsp;migrations.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I&amp;#8217;m still iterating on this project, so may change some things around as
I go. For the moment, this allowed me to manage the database schema
easily in multiple&amp;nbsp;databases.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=DKzL5rTzo7s:TABi6Os1_W8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=DKzL5rTzo7s:TABi6Os1_W8:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/DKzL5rTzo7s" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/postgres-database-migrations-with-python.html</feedburner:origLink></entry><entry><title>Reading email in Chinese with Python</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/RTeMLgQxDBc/reading-email-in-chinese-with-python.html" rel="alternate" /><updated>2012-10-15T16:41:00+02:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2012-10-15:reading-email-in-chinese-with-python.html</id><content type="html">&lt;p&gt;Read email from a mailbox, in Chinese, with Python. Sounded&amp;nbsp;easy.&lt;/p&gt;
&lt;p&gt;After playing at the python prompt and many Google searches later, still
no success. Then, I found &lt;a href="http://ginstrom.com/scribbles/2007/11/19/parsing-multilingual-email-with-python/"&gt;two&lt;/a&gt; &lt;a href="http://lobstertech.com/python_unicode.html#hands_on_with_asian_spam"&gt;articles&lt;/a&gt; that&amp;nbsp;helped.&lt;/p&gt;
&lt;p&gt;Turns out that there are a few tricks to getting email parsing to work
properly for multi-byte&amp;nbsp;languages.&lt;/p&gt;
&lt;p&gt;So, if you end up with strings something&amp;nbsp;like:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="o"&gt;=?&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;GB2312&lt;/span&gt;&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="n"&gt;Qingwen_Word_List&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;D3&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;D0&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;D2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;E2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;CB&lt;/span&gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;BC&lt;/span&gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;B5&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;C4&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;B4&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;CA&lt;/span&gt;&lt;/span&gt;&lt;span class="o"&gt;?=&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Or:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;CA&lt;/span&gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;AF&lt;/span&gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;CA&lt;/span&gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;AF&lt;/span&gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A8&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;AA&lt;/span&gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;D9&lt;/span&gt; &lt;span class="n"&gt;rock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;DA&lt;/span&gt;&lt;/span&gt; &lt;span class="n"&gt;stone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;DB&lt;/span&gt;&lt;/span&gt; &lt;span class="n"&gt;stone&lt;/span&gt; &lt;span class="n"&gt;inscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;DC&lt;/span&gt;&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;eight&lt;/span&gt; &lt;span class="n"&gt;ancient&lt;/span&gt; &lt;span class="n"&gt;musical&lt;/span&gt; &lt;span class="n"&gt;instruments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;B0&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;CB&lt;/span&gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;D2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;F4&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ba1&lt;/span&gt; &lt;span class="n"&gt;yin1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;C0&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;BC&lt;/span&gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;BB&lt;/span&gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A8&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;CCm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;BB&lt;/span&gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A8&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A2nhu&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A8&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;D9&lt;/span&gt; &lt;span class="n"&gt;cymbidium&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;A2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;&lt;span class="caps"&gt;DA&lt;/span&gt;&lt;/span&gt; &lt;span class="n"&gt;orchid&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then, you&amp;#8217;ll need two different approaches. One for the header strings,
and one for the body&amp;nbsp;text.&lt;/p&gt;
&lt;p&gt;Given an &lt;a href="http://docs.python.org/library/email.html"&gt;email&lt;/a&gt; message, either from a string or&amp;nbsp;file:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;email&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;email&lt;/span&gt;
&lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message_from_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;str_msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Then, headers can be read using something&amp;nbsp;like:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encoding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;Subject&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encoding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Which&amp;nbsp;gives:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;Qingwen&lt;/span&gt; &lt;span class="n"&gt;Word&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="err"&gt;有意思的词&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;In this case, the encoding can be read from the email message and is&amp;nbsp;&amp;#8216;gb2312&amp;#8217;.&lt;/p&gt;
&lt;p&gt;The body text needs a slightly different&amp;nbsp;approach:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="nb"&gt;unicode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_payload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_content_charset&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;replace&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;For:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="err"&gt;石&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;石&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="err"&gt;í&lt;/span&gt; &lt;span class="err"&gt;①&lt;/span&gt; &lt;span class="n"&gt;rock&lt;/span&gt; &lt;span class="err"&gt;②&lt;/span&gt; &lt;span class="n"&gt;stone&lt;/span&gt; &lt;span class="err"&gt;③&lt;/span&gt; &lt;span class="n"&gt;stone&lt;/span&gt; &lt;span class="n"&gt;inscription&lt;/span&gt; &lt;span class="err"&gt;④&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;eight&lt;/span&gt; &lt;span class="n"&gt;ancient&lt;/span&gt; &lt;span class="n"&gt;musical&lt;/span&gt; &lt;span class="n"&gt;instruments&lt;/span&gt; &lt;span class="err"&gt;八音&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ba1&lt;/span&gt; &lt;span class="n"&gt;yin1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;兰花&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="err"&gt;花&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;nhu&lt;/span&gt;&lt;span class="err"&gt;ā&lt;/span&gt; &lt;span class="err"&gt;①&lt;/span&gt; &lt;span class="n"&gt;cymbidium&lt;/span&gt; &lt;span class="err"&gt;②&lt;/span&gt; &lt;span class="n"&gt;orchid&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The &lt;a href="http://docs.python.org/library/functions.html?highlight=unicode#unicode"&gt;&amp;#8216;replace&amp;#8217;&lt;/a&gt; option will mark unknown characters using U+&lt;span class="caps"&gt;FFFD&lt;/span&gt;,
rather than throw an&amp;nbsp;exception.&lt;/p&gt;
&lt;p&gt;This approach should work for most languages. Getting the various
decodings sorted out allowed me to move forward on a project I&amp;#8217;m working
on. Now to re-implement it test&amp;nbsp;first.&lt;/p&gt;
&lt;p&gt;I know the format of the emails coming in, so can ignore multi-part &lt;span class="caps"&gt;MIME&lt;/span&gt;
messages. If you are looking for some more details on how to handle
them, check out &lt;a href="http://ginstrom.com/scribbles/2007/11/19/parsing-multilingual-email-with-python/"&gt;this article&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you were curious about the =&lt;span class="caps"&gt;DA&lt;/span&gt; encoding, it is called
&lt;a href="http://en.wikipedia.org/wiki/Quoted-printable"&gt;quoted-printable&lt;/a&gt; (&lt;a href="http://tools.ietf.org/html/rfc2045#section-6.7"&gt;&lt;span class="caps"&gt;RFC&lt;/span&gt;&lt;/a&gt;).&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=RTeMLgQxDBc:Y9rKHrJOMjw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=RTeMLgQxDBc:Y9rKHrJOMjw:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/RTeMLgQxDBc" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/reading-email-in-chinese-with-python.html</feedburner:origLink></entry><entry><title>Good Strategy Bad Strategy</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/-DFmAJwzRL4/good-strategy-bad-strategy.html" rel="alternate" /><updated>2012-06-24T22:53:00+02:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2012-06-24:good-strategy-bad-strategy.html</id><content type="html">&lt;p&gt;My current reading list is mixed between coding, decision making, agile,
and strategy. Richard Rumelt&amp;#8217;s &lt;a href="http://www.amazon.com/gp/product/B004J4WKEC/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=pseudofish-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=390957&amp;amp;creativeASIN=B004J4WKEC"&gt;Good Strategy Bad Strategy&lt;/a&gt; stands out
as an interesting and entertaining&amp;nbsp;read.&lt;/p&gt;
&lt;p&gt;I liked how he outlined good strategy, and also how to identify bad
strategy. This really helps in pushing through from a good enough
attempt to a strategy that will make a&amp;nbsp;difference.&lt;/p&gt;
&lt;p&gt;Some&amp;nbsp;quotes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Good strategy almost always looks this simple and obvious and does not
take a thick deck of PowerPoint slides to explain. It does not pop out
of some “strategic management” tool, matrix, chart, triangle, or
fill-in-the-blanks scheme. Instead, a talented leader identifies the
one or two critical issues in the situation—the pivot points that can
multiply the effectiveness of effort—and then focuses and concentrates
action and resources on&amp;nbsp;them.&lt;/p&gt;
&lt;p&gt;Good strategy requires leaders who are willing and able to say no to a
wide variety of actions and interests. Strategy is at least as much
about what an organization does not do as it is about what it&amp;nbsp;does.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On identifying bad&amp;nbsp;strategy:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I have condensed my list of its key hallmarks to the four listed in
the beginning of this chapter: fluff, the failure to face the
challenge, mistaking goals for strategy, and bad strategic&amp;nbsp;objectives.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;On the structure of a good&amp;nbsp;strategy:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The kernel of a strategy contains three elements: a diagnosis, a
guiding policy, and coherent action. The guiding policy specifies the
approach to dealing with the obstacles called out in the diagnosis. It
is like a signpost, marking the direction forward but not defining the
details of the trip. Coherent actions are feasible coordinated
policies, resource commitments, and actions designed to carry out the
guiding&amp;nbsp;policy.&lt;/p&gt;
&lt;p&gt;The problem of coming up with a good strategy has the same logical
structure as the problem of coming up with a good scientific
hypothesis. The key differences are that most scientific knowledge is
broadly shared, whereas you are working with accumulated wisdom about
your business and your industry that is unlike anyone else’s. A good
strategy is, in the end, a hypothesis about what will&amp;nbsp;work.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The book provides insight into the structure of a good strategy.
However, it stops short of providing actionable techniques or analysis
to help you get there. In this, it advocates strategy work being done by
someone with a deep understanding of the business and competitive&amp;nbsp;landscape.&lt;/p&gt;
&lt;p&gt;This left me wanting more, and fortunately there are books out there
that provide guidelines on this type of analysis. I see a few &lt;a href="http://www.amazon.com/s/ref=nb_sb_noss_1?url=search-alias%3Daps&amp;amp;field-keywords=Michael+Porter"&gt;Michael
Porter&lt;/a&gt; books in my future&amp;nbsp;reading.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=-DFmAJwzRL4:wNRt0Uz_E4U:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=-DFmAJwzRL4:wNRt0Uz_E4U:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/-DFmAJwzRL4" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/good-strategy-bad-strategy.html</feedburner:origLink></entry><entry><title>Debugging Python with PDB</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/BxBsqaHeDkU/debugging-python-with-pdb.html" rel="alternate" /><updated>2012-05-03T02:51:00+02:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2012-05-03:debugging-python-with-pdb.html</id><content type="html">&lt;p&gt;I suck at using debuggers, largely because I don&amp;#8217;t launch them often&amp;nbsp;enough.&lt;/p&gt;
&lt;p&gt;Fortunately, this year&amp;#8217;s PyCon had a &lt;a href="http://pyvideo.org/video/644/introduction-to-pdb"&gt;great talk&lt;/a&gt; from Chris McDonough
on how to get started with Python&amp;#8217;s debugger, &lt;a href="http://docs.python.org/library/pdb.html"&gt;&lt;span class="caps"&gt;PDB&lt;/span&gt;&lt;/a&gt;. The friendly
people at Stockholm&amp;#8217;s &lt;a href="http://www.meetup.com/pysthlm/"&gt;Python meet-up&lt;/a&gt; suggested&amp;nbsp;it.&lt;/p&gt;
&lt;iframe width="420" height="315" src="http://www.youtube.com/embed/vfPtGsSJldg" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;I made notes while watching, to remove excuses from future me on
launching&amp;nbsp;pdb.&lt;/p&gt;
&lt;p&gt;Where you want to have the debugger start, add the following&amp;nbsp;code:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;pdb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;pdb&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_trace&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This drops you into a &lt;span class="caps"&gt;PDB&lt;/span&gt; prompt. This is more helpful than putting in
yet more print&amp;nbsp;statements.&lt;/p&gt;
&lt;p&gt;Some helpful commands once you&amp;#8217;re&amp;nbsp;in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;l - list&amp;nbsp;code&lt;/li&gt;
&lt;li&gt;args - arguments to current&amp;nbsp;function&lt;/li&gt;
&lt;li&gt;p &amp;lt;var&gt; - print a&amp;nbsp;var&lt;/li&gt;
&lt;li&gt;pp &amp;lt;var&gt; - pretty print a&amp;nbsp;var&lt;/li&gt;
&lt;li&gt;n -&amp;nbsp;next&lt;/li&gt;
&lt;li&gt;s -&amp;nbsp;step&lt;/li&gt;
&lt;li&gt;w - where (stack trace for current&amp;nbsp;position)&lt;/li&gt;
&lt;li&gt;h -&amp;nbsp;help&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While in &lt;span class="caps"&gt;PDB&lt;/span&gt;, you can evaluate python code. The evaluated code won&amp;#8217;t
impact the running&amp;nbsp;program.&lt;/p&gt;
&lt;p&gt;For a bonus trick if you&amp;#8217;re using Emacs, try out &lt;a href="http://wiki.zope.org/klm/PDBTrack"&gt;pdb track mode&lt;/a&gt;.
Launch your python process to be debugged in an emacs shell (M-x shell).
Stepping through the code in pdb will track with a source code&amp;nbsp;buffer.&lt;/p&gt;
&lt;p&gt;This worked out of the box with my emacs config. Your milage may&amp;nbsp;vary.&lt;/p&gt;
&lt;p&gt;I may actually start to enjoy debugging&amp;nbsp;now!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=BxBsqaHeDkU:IJSRVi98I5w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=BxBsqaHeDkU:IJSRVi98I5w:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/BxBsqaHeDkU" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/debugging-python-with-pdb.html</feedburner:origLink></entry><entry><title>Unit testing in Python with folder watching</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/pnI_9NESalE/unit-testing-in-python-with-folder-watching.html" rel="alternate" /><updated>2012-03-14T05:09:00+01:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2012-03-14:unit-testing-in-python-with-folder-watching.html</id><content type="html">&lt;p&gt;Unit testing is good. Running unit tests manually is&amp;nbsp;annoying.&lt;/p&gt;
&lt;p&gt;Rspec has a great addition in &lt;a href="http://lostechies.com/derickbailey/2010/05/03/zentest-autospec-is-an-rspec-tdder-s-best-friend/"&gt;autospec&lt;/a&gt;, which automatically re-runs
specs that are changed or have the associated code changed. This model
of working has a long history in the ruby community, with &lt;a href="http://nubyonrails.com/articles/autotest-rails"&gt;autotest&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I wanted a similar thing for python/&lt;a href="http://readthedocs.org/docs/nose/en/latest/"&gt;nose&lt;/a&gt;, but hadn&amp;#8217;t had much&amp;nbsp;luck.&lt;/p&gt;
&lt;p&gt;The solution is &lt;a href="http://pytest.org/latest/"&gt;py.test&lt;/a&gt;, with some plugins&amp;nbsp;added.&lt;/p&gt;
&lt;p&gt;This was suggested to me at the &lt;a href="http://www.meetup.com/pysthlm/"&gt;Stockholm Python user group&lt;/a&gt;, and I
am very grateful. My testing life is now much&amp;nbsp;simpler.&lt;/p&gt;
&lt;p&gt;To get started, try something&amp;nbsp;like:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;sudo&lt;/span&gt; &lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;xdist&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cov&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The simple way to get started is to watch your tests&amp;nbsp;folder:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now as you change files, the relevant tests will automatically be
re-run. Perfect to display on that second&amp;nbsp;monitor.&lt;/p&gt;
&lt;p&gt;As I was working on some legacy code, I was looking to improve the test
coverage, so wanted to see how that was going with &lt;a href="http://pypi.python.org/pypi/pytest-cov"&gt;pytest-cov&lt;/a&gt;:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;cov&lt;/span&gt; &lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Adding the &lt;em&gt;package.name&lt;/em&gt; for your main package means you won&amp;#8217;t generate
coverage for libraries you are using. Makes the output&amp;nbsp;simpler.&lt;/p&gt;
&lt;p&gt;Still not quite happy, it wasn&amp;#8217;t showing me which lines I needed
coverage on. No&amp;nbsp;problem:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;py&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;cov&lt;/span&gt; &lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;cov&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;report&lt;/span&gt; &lt;span class="n"&gt;term&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;missing&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;For comparison, here is how to get similar results from nose, but
without watch&amp;nbsp;support:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="n"&gt;nosetests&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nosetests&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;with&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;coverage&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;cover&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;erase&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;cover&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;One hurdle I had with py.test was working with &lt;a href="http://twistedmatrix.com/trac/"&gt;Twisted&lt;/a&gt; based
test-cases. You need to ensure that you use a version of py.test later
than 2.0. Debian squeeze does not package this by default, so use pip to&amp;nbsp;install.&lt;/p&gt;
&lt;p&gt;The annoyance is if you change the code so it doesn&amp;#8217;t terminate. This
still needs a context switch to kill off the tests and re-run. Keeps me
focused on getting it right the first&amp;nbsp;time.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://pypi.python.org/pypi/pytest-xdist"&gt;pytest-xdist&lt;/a&gt; includes lots of really cool options, such as
distribution of tests across multiple cores, versions, hosts and&amp;nbsp;platforms.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve since discovered this &lt;a href="http://wiki.python.org/moin/PythonTestingToolsTaxonomy"&gt;comprehensive summary&lt;/a&gt; of the options
available. I&amp;#8217;m happy I found this after selecting &lt;a href="http://pytest.org/latest/"&gt;py.test&lt;/a&gt;, or I&amp;#8217;d
still be stuck in evaluation mode rather than writing&amp;nbsp;code.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update&lt;/em&gt;: check out &lt;a href="http://pypi.python.org/pypi/sniffer"&gt;sniffer&lt;/a&gt; if you want a more generic watcher&amp;nbsp;framework.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=pnI_9NESalE:A2nh5-x8mrQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=pnI_9NESalE:A2nh5-x8mrQ:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/pnI_9NESalE" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/unit-testing-in-python-with-folder-watching.html</feedburner:origLink></entry><entry><title>Sharpen the Saw: Typing</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/KUM-EuujtCA/sharpen-the-saw-typing.html" rel="alternate" /><updated>2012-03-07T00:14:00+01:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2012-03-07:sharpen-the-saw-typing.html</id><content type="html">&lt;p&gt;I once explained my job as an overpaid&amp;nbsp;typist.&lt;/p&gt;
&lt;p&gt;There is some truth in that, as much of my day is spent typing. Writing
code, taking notes for meetings, email, documentation, writing blogs&amp;nbsp;posts.&lt;/p&gt;
&lt;p&gt;It would make sense to become very good at&amp;nbsp;typing.&lt;/p&gt;
&lt;p&gt;The basics are often overlooked. You can get a lot of benefit from
paying attention to&amp;nbsp;them.&lt;/p&gt;
&lt;p&gt;For typing, it comes down to three main&amp;nbsp;areas:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Accuracy&lt;/li&gt;
&lt;li&gt;Speed&lt;/li&gt;
&lt;li&gt;Touch&amp;nbsp;typing&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Touch typing is perhaps the most important aspect of this. You need to
be able to type without looking at the keyboard. If you get really good,
you shouldn&amp;#8217;t need to even look at the screen to confirm what you&amp;#8217;re&amp;nbsp;typing.&lt;/p&gt;
&lt;p&gt;Accuracy and speed can be built together. Focus on accuracy to start
with, and then stretch for speed. There is no point going faster if you
can&amp;#8217;t maintain a high&amp;nbsp;accuracy.&lt;/p&gt;
&lt;p&gt;I found two websites to be helpful in my quest for improved typing&amp;nbsp;skills:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://wwwtyro.github.com/keyzen/"&gt;Keyzen&lt;/a&gt; — a site focused on improving typing for&amp;nbsp;programmers.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://speedtest.10fastfingers.com/"&gt;10 fast fingers&lt;/a&gt; — general typing improvement with natural
    language&amp;nbsp;exercises.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, the other thing to do to improve typing is to do lots of
typing. If you are writing lots of code, email or documents, then focus
on your typing while you are doing&amp;nbsp;it.&lt;/p&gt;
&lt;p&gt;It helps to have a good environment for typing, such as a comfortable
keyboard, good posture, but you know this already. Add it to the list of
things to focus&amp;nbsp;on.&lt;/p&gt;
&lt;p&gt;Also, make sure that you are using a program that can keep up with you
as you type. I find &lt;span class="caps"&gt;MS&lt;/span&gt; Word to lag when in full &lt;span class="caps"&gt;WYSIWG&lt;/span&gt; mode, whereas
emacs and vi always manage to keep&amp;nbsp;up!&lt;/p&gt;
&lt;p&gt;Update: You may also want to check out &lt;a href="http://typespeed.sourceforge.net/"&gt;Typespeed&lt;/a&gt;.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=KUM-EuujtCA:rD23Vkv4Urk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=KUM-EuujtCA:rD23Vkv4Urk:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/KUM-EuujtCA" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/sharpen-the-saw-typing.html</feedburner:origLink></entry><entry><title>About Face, Edition 3</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/UwJEOiBGVas/about-face-edition-3.html" rel="alternate" /><updated>2012-02-29T17:21:00+01:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2012-02-29:about-face-edition-3.html</id><content type="html">&lt;blockquote&gt;
&lt;p&gt;In any field, if you expand your view to know all the ecosystem around
you it’s&amp;nbsp;beneficial.&lt;/p&gt;
&lt;p&gt;—&lt;a href="http://intenseminimalism.com/2011/designers-shouldnt-code-the-digital-duo/"&gt;Davide&amp;nbsp;Casali&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you are a developer, a product owner, or manage a development team,
much of the input is going to be about product design. It is very useful
to understand a bit about a good design process, so you can better ask
questions and help refine the design based on technical&amp;nbsp;constraints.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.amazon.com/gp/product/B001C323BI/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=pseudofish-20&amp;amp;linkCode=as2&amp;amp;camp=217145&amp;amp;creative=399373&amp;amp;creativeASIN=B001C323BI"&gt;About Face&lt;/a&gt;, by Alan Cooper, is a great book to start&amp;nbsp;with.&lt;/p&gt;
&lt;p&gt;I highlighted much of it on my&amp;nbsp;Kindle!&lt;/p&gt;
&lt;p&gt;Here are some&amp;nbsp;quotes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Good design makes users more&amp;nbsp;effective.&lt;/p&gt;
&lt;p&gt;Customers, although they might be able to articulate the problems with
an interaction, are not often capable of visualizing the solutions to
those&amp;nbsp;problems.&lt;/p&gt;
&lt;p&gt;One of the most powerful tools designers bring to the table is&amp;nbsp;empathy&lt;/p&gt;
&lt;p&gt;One of the most dangerous practices in product development is
isolating designers from the users because doing so eliminates
empathic&amp;nbsp;knowledge.&lt;/p&gt;
&lt;p&gt;narrative is also one of our most powerful creative&amp;nbsp;methods.&lt;/p&gt;
&lt;p&gt;What would a helpful human do? What would a thoughtful, considerate
interaction feel&amp;nbsp;like?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;All ideas are broken down into discrete sections, with lots of detail
and examples on how to implement this with your&amp;nbsp;customers.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Goal-Directed Design combines techniques of ethnography, stakeholder
interviews, market research, detailed user models, scenario-based
design, and a core set of interaction principles and&amp;nbsp;patterns.&lt;/p&gt;
&lt;p&gt;This process can be roughly divided into six phases: Research,
Modeling, Requirements Definition, Framework Definition, Refinement,
and&amp;nbsp;Support&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The book discusses the mindset required to be a good&amp;nbsp;designer:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;in anything at all, perfection is finally attained not when there is
no longer anything to add, but when there is no longer anything to
take&amp;nbsp;away&lt;/p&gt;
&lt;p&gt;Next time you find yourself crowing about what cool interaction you&amp;#8217;ve
designed, just remember that the ultimate user interface for most
purposes is no interface at&amp;nbsp;all.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The first part of the book focuses on processes to elicit a good design.
The latter part of the book covers specific examples found in user
interface design and attempts to encode common&amp;nbsp;patterns.&lt;/p&gt;
&lt;p&gt;I found the first section much more valuable to how I think about
designing a new product. The latter parts I felt were obvious, although
that is perhaps their&amp;nbsp;importance.&lt;/p&gt;
&lt;p&gt;Well worth a&amp;nbsp;read.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: Bret&amp;#8217;s &lt;a href="http://worrydream.com/#!/MagicInk"&gt;Magic Ink&lt;/a&gt; is a useful counterpoint to About&amp;nbsp;Face.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=UwJEOiBGVas:qhSBjYLjnSs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=UwJEOiBGVas:qhSBjYLjnSs:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/UwJEOiBGVas" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/about-face-edition-3.html</feedburner:origLink></entry><entry><title>Positioning</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/dIdny-LPouY/positioning.html" rel="alternate" /><updated>2011-11-28T20:37:00+01:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2011-11-28:positioning.html</id><content type="html">&lt;p&gt;&lt;a href="http://www.amazon.com/gp/product/B000SEGIW2/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=pseudofish-20&amp;amp;linkCode=as2&amp;amp;camp=217145&amp;amp;creative=399373&amp;amp;creativeASIN=B000SEGIW2"&gt;Positioning&lt;/a&gt;, by Al Ries and Jack Trout, has long been on my &lt;em&gt;to
read&lt;/em&gt; list, and I wish I had read it&amp;nbsp;sooner.&lt;/p&gt;
&lt;p&gt;The core message of how to position a product is becoming more relevant
as the marketplace continues to&amp;nbsp;crowd.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In our overcommunicated society, the name of the game today is
positioning. And only the better players are going to&amp;nbsp;survive.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The book draws on a wide range of examples of different products, where
a &lt;em&gt;product&lt;/em&gt; could be a type of beer, the Catholic Church or your own&amp;nbsp;career.&lt;/p&gt;
&lt;p&gt;The key message is that your products position is determined by how it
fits into the consumer&amp;#8217;s mind. All the things that matter to you, to
your company, are irrelevant if you can&amp;#8217;t create a distinct position to
separate you from everything&amp;nbsp;else.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Experience has shown that a positioning exercise is a search for the
obvious. Those are the easiest concepts to communicate because they
make the most sense to the recipient of a&amp;nbsp;message.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The authors are quite scathing about &amp;#8220;me too&amp;#8221; products that attempt to
beat out a competitor by going head-to-head. Many examples are provided
within the&amp;nbsp;book.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The suicidal bent of companies that go head-on against established
competition is hard to&amp;nbsp;understand.&lt;/p&gt;
&lt;p&gt;To repeat, the first rule of positioning is: To win the battle for the
mind, you can’t compete head-on against a company that has a strong,
established position. You can go around, under or over, but never head
to&amp;nbsp;head.&lt;/p&gt;
&lt;p&gt;The leader owns the high ground. The No. 1 position in the prospect’s
mind. The top rung of the product&amp;nbsp;ladder.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The book covers a range of detail levels, and dips into more detail on
key areas such as product&amp;nbsp;naming:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;As a guide, the five most common initial letters are S, C, P, A, and
T. The five least common are X, Z, Y, Q, and K. One out of eight
English words starts with an S. One out of 3000 starts with an&amp;nbsp;X.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The authors are often quite blunt as to how they see things. This is a
refreshing change from most business&amp;nbsp;books:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Creative people often resist positioning thinking because they believe
it restricts their creativity. And you know what? It does. Positioning
thinking does restrict&amp;nbsp;creativity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I gained a lot of insight into how products have succeeded, or not, by
reading this book. The examples are clear and will easily map to
situations you are&amp;nbsp;experiencing.&lt;/p&gt;
&lt;p&gt;I recommend &lt;a href="http://www.amazon.com/gp/product/B000SEGIW2/ref=as_li_ss_tl?ie=UTF8&amp;amp;tag=pseudofish-20&amp;amp;linkCode=as2&amp;amp;camp=217145&amp;amp;creative=399373&amp;amp;creativeASIN=B000SEGIW2"&gt;Positioning&lt;/a&gt; for anyone involved in creating something
new. This is a book that I will&amp;nbsp;re-read.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=dIdny-LPouY:QJ-36lT6K-A:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=dIdny-LPouY:QJ-36lT6K-A:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/dIdny-LPouY" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/positioning.html</feedburner:origLink></entry><entry><title>Emacs or Vim</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/dsRcZJshRr0/emacs-or-vim.html" rel="alternate" /><updated>2011-11-25T01:33:00+01:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2011-11-25:emacs-or-vim.html</id><content type="html">&lt;p&gt;After over 12 years of using Vi(m), and a brief fling with TextMate, I
&lt;a href="http://pseudofish.com/blog/2010/09/18/learning-clojure-with-google-app-engine-and-emacs/"&gt;started&lt;/a&gt; &lt;a href="http://pseudofish.com/blog/2011/04/14/emacs-update/"&gt;using&lt;/a&gt; Emacs as my primary&amp;nbsp;editor.&lt;/p&gt;
&lt;h3&gt;Emacs&lt;/h3&gt;
&lt;p&gt;The switch has been very positive. The learning curve has been
relatively steep, as my expectations from a text editor are quite&amp;nbsp;high.&lt;/p&gt;
&lt;p&gt;Emacs strength (and weakness) is that it is incredibly extensible. Where
I&amp;#8217;m finding Emacs a win over Vim is that I don&amp;#8217;t have to leave Emacs to
get things done. With Vim, I tend to use more of a mix of terminal
windows and the&amp;nbsp;editor.&lt;/p&gt;
&lt;p&gt;I began by using the &lt;a href="https://github.com/technomancy/emacs-starter-kit"&gt;starter kit&lt;/a&gt; to get going with Emacs
configuration. This made it quicker to get moving, but added a lot of
things I ended up not needing. After getting more comfortable with
elisp, I started from scratch and rebuilt my &lt;a href="https://github.com/gmwils/dotfiles/tree/master/emacs.d"&gt;emacs.d folder&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To jump in quickly, I also purchased the tutorial video from
&lt;a href="https://peepcode.com/products/meet-emacs"&gt;Peepcode&lt;/a&gt;. This certainly helped as emacs is a mental shift coming
from&amp;nbsp;Vim.&lt;/p&gt;
&lt;p&gt;The big benefit I have found with Emacs is the extension packages. These
can be installed from the &lt;span class="caps"&gt;ELPA&lt;/span&gt; &lt;a href="http://www.emacswiki.org/emacs/ELPA"&gt;repository&lt;/a&gt;, and include a range of
different &lt;em&gt;modes&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Some of my favourite modes&amp;nbsp;include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.emacswiki.org/emacs/ParEdit"&gt;paredit&lt;/a&gt; - essential for any lisp, it ensures your brackets&amp;nbsp;match.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jblevins.org/projects/deft/"&gt;deft&lt;/a&gt; - simplified note taking. (I it sync via &lt;a href="http://emacs-fu.blogspot.com/2011/09/quick-note-taking-with-deft-and-org.html"&gt;Dropbox&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.emacswiki.org/emacs/Magit"&gt;magit&lt;/a&gt; - comprehensive Git workflow within&amp;nbsp;Emacs&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jblevins.org/projects/markdown-mode/"&gt;markdown-mode&lt;/a&gt; - my current default for writing notes, although
    I&amp;#8217;m leaning towards org-mode&amp;nbsp;now.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://orgmode.org/"&gt;org-mode&lt;/a&gt; - highly capable note taking mode, with export options
    to everything. You can use it to write a book, create slides, or
    manage your todo&amp;nbsp;list.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On the Mac, I&amp;#8217;ve been using &lt;a href="http://aquamacs.org/"&gt;Aquamacs&lt;/a&gt; for most of my text editing,
and used &lt;a href="http://www.macports.org/"&gt;macports&lt;/a&gt; to install the command line&amp;nbsp;client.&lt;/p&gt;
&lt;p&gt;I have yet to try Emacs on Windows, as I haven&amp;#8217;t been using Windows much
at all. There is a release available &lt;a href="http://www.gnu.org/software/emacs/windows/Getting-Emacs.html#Getting-Emacs"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After cleaning up my .emacs.d configuration, I&amp;#8217;ve now started using
Emacs on Linux servers I use regularly. For temporary servers, I&amp;#8217;ll
fallback to Vim as Emacs is often not&amp;nbsp;installed.&lt;/p&gt;
&lt;p&gt;If you want to improve your emacs skills follow @&lt;a href="https://twitter.com/emacs_knight"&gt;emacs_knight&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Vim&lt;/h3&gt;
&lt;p&gt;To get started with Vim, it is worth reading &lt;a href="http://robots.thoughtbot.com/post/13164810557/the-vim-learning-curve-is-a-myth"&gt;The Vim Learning Curve is
a Myth&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Over the years, the popular mythology around vim has become that it’s
insanely difficult to learn; a task to be attempted by only those with
the thickest of neck-beards. I’ve heard dozens of times from folks who
are convinced it will take them months to reach&amp;nbsp;proficiency.&lt;/p&gt;
&lt;p&gt;These beliefs are &lt;em&gt;false&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;My feeling is that Vim is unrivalled for the simple task of text
editing. Even after a day or two of learning, you will be&amp;nbsp;faster.&lt;/p&gt;
&lt;p&gt;Where things get a bit more complicated is when you start to realise
that text editing isn&amp;#8217;t the whole story for a text&amp;nbsp;editor.&lt;/p&gt;
&lt;p&gt;Platform support is superb. The first thing I do to a Windows machine is
install &lt;a href="http://www.vim.org/download.php"&gt;Vim&lt;/a&gt;. It is rare for an application with a Unix heritage to
be so comfortable on&amp;nbsp;Windows.&lt;/p&gt;
&lt;p&gt;Historically, I hadn&amp;#8217;t been a fan of the graphical version of
&lt;a href="http://code.google.com/p/macvim/"&gt;MacVim&lt;/a&gt;. This is something that is much better in recent releases.
Load times are much&amp;nbsp;improved.&lt;/p&gt;
&lt;p&gt;Integration into external tools is where I feel Vim is lacking a bit.
With the number of developers migrating from TextMate to Vim, this gap
is being rapidly addressed. However, Vim isn&amp;#8217;t as extensible as some
other&amp;nbsp;editors.&lt;/p&gt;
&lt;p&gt;I really noticed this when trying out Clojure programming. If you are
dealing with a &lt;span class="caps"&gt;REPL&lt;/span&gt; based environment, Vim has a way to&amp;nbsp;go.&lt;/p&gt;
&lt;h3&gt;Closing&amp;nbsp;Thoughts&lt;/h3&gt;
&lt;p&gt;If you aren&amp;#8217;t using either of them, it&amp;#8217;s not too late to start. You
can&amp;#8217;t make a bad&amp;nbsp;choice.&lt;/p&gt;
&lt;p&gt;If you are already using either Emacs or Vim,&amp;nbsp;enjoy!&lt;/p&gt;
&lt;p&gt;Both are great editors that allow you to be incredibly productive at
working with text. Try learning a new feature each week. You use your
text editor so often that a small improvement is a major&amp;nbsp;payoff.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=dsRcZJshRr0:LfT38ZBmw0c:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=dsRcZJshRr0:LfT38ZBmw0c:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/dsRcZJshRr0" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/emacs-or-vim.html</feedburner:origLink></entry><entry><title>Calculating earlier dates using a shell script</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/H-2Y5R-E6Zw/calculating-earlier-dates-using-a-shell-script.html" rel="alternate" /><updated>2011-10-07T01:40:00+02:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2011-10-07:calculating-earlier-dates-using-a-shell-script.html</id><content type="html">&lt;p&gt;Mongo has a database size limit in 32 bit mode, so I want to purge out
items that are less than a certain date in the past. I decided that it
would be easy to write a simple shell script to run the&amp;nbsp;query.&lt;/p&gt;
&lt;p&gt;The tricky part was calculating dates in shell. This is what I ended up&amp;nbsp;with:&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;

&lt;span class="nv"&gt;MONTHS_AGO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3
&lt;span class="nv"&gt;DATE_AGO_EPOCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;date +%s&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;$MONTHS_AGO&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;31&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;3600&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
&lt;span class="nv"&gt;&lt;span class="caps"&gt;OSTYPE&lt;/span&gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;uname&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="nv"&gt;&lt;span class="caps"&gt;FORMAT&lt;/span&gt;&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;+%Y-%m-%d&amp;#39;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Linux&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$&lt;span class="caps"&gt;OSTYPE&lt;/span&gt;&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; ; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="k"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;DATE_AGO_ISO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;date -d &lt;span class="s2"&gt;&amp;quot;1970-01-01 00:00 &lt;span class="caps"&gt;UTC&lt;/span&gt; + $DATE_AGO_EPOCH seconds&amp;quot;&lt;/span&gt; &lt;span class="nv"&gt;$&lt;span class="caps"&gt;FORMAT&lt;/span&gt;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;
&lt;span class="k"&gt;  &lt;/span&gt;&lt;span class="nv"&gt;DATE_AGO_ISO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;date -r &lt;span class="nv"&gt;$DATE_AGO_EPOCH&lt;/span&gt; &lt;span class="nv"&gt;$&lt;span class="caps"&gt;FORMAT&lt;/span&gt;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="nv"&gt;DB_CMD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;db.items.find( { publish_date : { \$lt : \&amp;quot;$DATE_AGO_ISO\&amp;quot; } } ).count()&amp;quot;&lt;/span&gt;
&lt;span class="c"&gt;# DB_CMD=&amp;quot;db.items.remove( { publish_date : { \$lt : \&amp;quot;$DATE_AGO_ISO\&amp;quot; } } )&amp;quot;&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$DB_CMD&lt;/span&gt; | mongo pz
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This now provides a simple way of purging out old items that can be
called from&amp;nbsp;cron.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=H-2Y5R-E6Zw:R0OrfWq-B-8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=H-2Y5R-E6Zw:R0OrfWq-B-8:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/H-2Y5R-E6Zw" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/calculating-earlier-dates-using-a-shell-script.html</feedburner:origLink></entry><entry><title>Storm - a real time Hadoop like system in Clojure</title><link href="http://feedproxy.google.com/~r/Pseudofish/~3/JkfA5M4nTp8/storm-a-real-time-hadoop-like-system-in-clojure.html" rel="alternate" /><updated>2011-09-26T02:33:00+02:00</updated><author><name>gmwils</name></author><id>tag:pseudofish.com,2011-09-26:storm-a-real-time-hadoop-like-system-in-clojure.html</id><content type="html">&lt;p&gt;I am very excited about the potential unleashed by &lt;a href="https://github.com/nathanmarz/storm"&gt;Storm&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Previously at BackType, &lt;a href="https://twitter.com/nathanmarz"&gt;Nathan Marz&lt;/a&gt; has now built Storm into Twitter
and then open sourced the&amp;nbsp;platform.&lt;/p&gt;
&lt;p&gt;Storm opens up a lot of possibilities, by bringing real-time distributed
processing together in an elegant way. And it is built in&amp;nbsp;Clojure!&lt;/p&gt;
&lt;p&gt;Some useful&amp;nbsp;links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nathanmarz/storm/wiki/Rationale"&gt;Rationale&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.slideshare.net/nathanmarz/storm-distributed-and-faulttolerant-realtime-computation"&gt;Slides&lt;/a&gt; - detailed presentation on Storm by&amp;nbsp;Nathan&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nathanmarz/storm-starter"&gt;Starter project&lt;/a&gt; - a few basic demo use&amp;nbsp;cases&lt;/li&gt;
&lt;li&gt;&lt;a href="http://groups.google.com/group/storm-user"&gt;Mailing&amp;nbsp;List&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://storm.twitsprout.com/"&gt;Taking the Emmys by Storm&lt;/a&gt; - an hour long video of how to use
    Storm to aggregate data from Twitter in realtime to spot&amp;nbsp;trends.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While playing around I wanted to try from Clojure (most examples are in
Java). There is a great &lt;span class="caps"&gt;DSL&lt;/span&gt; for Clojure that makes using Storm super
easy. I forked the &lt;a href="https://github.com/gmwils/storm-starter/"&gt;storm-starter&lt;/a&gt; project to add &lt;a href="https://github.com/gmwils/storm-starter/blob/master/src/clj/storm/starter/wordcount.clj"&gt;examples&lt;/a&gt; based
on a &lt;a href="https://gist.github.com/1228302"&gt;Gist&lt;/a&gt; from&amp;nbsp;Nathan.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=JkfA5M4nTp8:fsscVbX2cgM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/Pseudofish?a=JkfA5M4nTp8:fsscVbX2cgM:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/Pseudofish?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/Pseudofish/~4/JkfA5M4nTp8" height="1" width="1"/&gt;</content><feedburner:origLink>http://pseudofish.com/storm-a-real-time-hadoop-like-system-in-clojure.html</feedburner:origLink></entry></feed>
