<?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">
    <title>Contentment</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/" />
    
    <id>tag:contentment.org,2010-05-12://3</id>
    <updated>2010-09-20T02:23:07Z</updated>
    <subtitle>The place where I get my geek on...</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 5.04</generator>

<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/Contentment" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="contentment" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
    <title>My Very Own Phone System</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2010/09/my-very-own-phone-system.html" />
    <id>tag:contentment.org,2010://3.727</id>

    <published>2010-09-20T01:05:41Z</published>
    <updated>2010-09-20T02:23:07Z</updated>

    <summary>Okay, so I’ve now hacked my home phone system. The ultimate goal here is to make it so that we don’t pay so much for a land line we hardly use. However, we still want a home phone system. By...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
        <category term="Telephony" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="asterisk" label="Asterisk" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="freepbx" label="FreePBX" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="home" label="home" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="openvbx" label="OpenVBX" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="phone" label="phone" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="sip" label="SIP" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="techonology" label="techonology" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="telephony" label="telephony" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p>Okay, so I&#8217;ve now hacked my home phone system. The ultimate goal here is to make it so that we don&#8217;t pay so much for a land line we hardly use. However, we still want a home phone system. By popular demand (HT: Jim, Melissa), I&#8217;m posting what I&#8217;ve done so far and what I plan to do still.</p>

<h3>Phase 1: Build a PBX</h3>

<p>I have this old desktop machine sitting around that has been my guinea pig over time for various projects. It&#8217;s a P2 933MHz (or something) and works pretty well in this role for being 8-10 years old. It&#8217;s last job was to run Windows XP so I could runt he upgrade software to install Android 2.1 on my phone, though that actually failed because the computer only has USB 1.0 and the upgrade required USB 2.0. </p>

<p>Before that, it was an experiment to setup MythTV, which worked, but I decided I didn&#8217;t want to buy the hardware required to make a box work when we almost never watch anything on TV with Netflix and Hulu. That would only be really beneficial if I was more into sports.</p>

<p>Anyway, I digress&#8230;</p>

<p>I started off using <a href="http://incrediblepbx.com/">The Incredible PBX</a>, which is a distribution of <a href="http://www.centos.org/">Centos Linux</a>, <a href="http://www.asterisk.org/">Asterisk</a>, and <a href="http://www.freepbx.org/">FreePBX</a>. Setting that up with <a href="https://www.google.com/voice#">Google Voice</a> and <a href="http://www.sipgate.com/">SIPgate</a> was pretty easy. I just used the instructions at The Incredible PBX.</p>

<p>Once I could get that done. I was ready to move on to phase two.</p>

<h3>Phase 2: Installing a VoIP Gateway</h3>

<div style="float:left;margin:3px">
<iframe src="http://rcm.amazon.com/e/cm?lt1=_blank&bc1=000000&IS2=1&bg1=FFFFFF&fc1=000000&lc1=0000FF&t=openscri-20&o=1&p=8&l=as1&m=amazon&f=ifr&md=10FE9736YVPPT7A0FBG2&asins=B000FKP55U" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
</div>

<p>I purchased a LinkSys SPA-3102 to handle the VoIP gateway. This box now runs a little over $60 and works as a router with one WAN port and one LAN port (I really only need one of these ports) and two voice ports. One FXS port for connecting to the PSTN (Public Switched Telephone Network) and one FXO port for power the house phone line. Utlimately, the FXS port will be unused, but by having this available, I&#8217;m able to install the VoIP system in phases without the risk of the phone system being down for a long time while I get everything figured out. If nothing else, I can always reset the box to the factory original settings and it works just like it wasn&#8217;t there.</p>

<p>In the process, I had to correct some deficiencies in my home phone network, which is pretty badly spliced together. It&#8217;s still badly spliced, but it&#8217;s a little better now.</p>

<p>Once it arrived, I installed the VoIP gateway and it just worked, which was pretty nice of it.</p>

<h3>Phase 3: VoIP Gateway and PBX Together</h3>

<p>I have just completed phase 3 of the process, which is to set up the trunk, extension, and routes in FreePBX/Asterisk and then setup the SPA-3102 so that it talks through the Asterisk server. This was pretty complicated. I found a couple different sites to help, but a <a href="http://www.freepbx.org/support/documentation/howtos/howto-linksys-spa-3102-sipura-spa-3000-freepbx">HOWTO</a> on FreePBX&#8217;s site got me about 95% there. </p>

<p>It did take some experimentation and I did need to setup the Line 1 interface as an extension too, but it works now. When a call comes in, it gets routed into the 700 extension group, which rings the house extension and any softphones we want to setup. I have it setup so that dialing out routes back out of this line, and it works. I also made sure to create a special emergency route that allows 911 calls to be routed out properly as well.</p>

<h3>Still to Come</h3>

<p>Okay, so this gets me to the point where I can start to experiment with the PBX to see what we can do with it. Things that come to mind are setting up night mode, where we can keep the phones from ringing after the kids are in bed unless the caller dials through a screening process. I can also setup dial-out through other services, which I&#8217;ve started to do, but haven&#8217;t finished. We also have fancy voice mail if we want to use it instead of the answering machine, we can have music on hold (woo-woo), etc. I haven&#8217;t figured out quite all I want to do with the box yet.</p>

<p>However, the ultimate goal is to reduce the cost of this line, which means I need to port the phone number to some other phone service that&#8217;s cheaper than the PSTN. The prime candidate at the moment is <a href="http://www.twilio.com/">Twilio</a>. They have an app called <a href="http://www.openvbx.org/">OpenVBX</a>, which sets up a private service that resembles Google Voice, but much more configurable. I can use that to ring a my phone at SIPgate, which will ring the house phone. Then, I can configure even more fancy things on the OpenVBX server, which will give me voicemail with SMS and email integration and transcriptions. I can ring our cell phones when someone calls the house and get all kinds of other whizbangs, for a $1/mo phone number + a few cents a minute in charges.</p>

<p>So, that&#8217;s what I&#8217;m experimenting with now.</p>

<p>Cheers.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>OWASP Top Ten</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2010/07/owasp-top-ten.html" />
    <id>tag:contentment.org,2010://3.712</id>

    <published>2010-07-31T12:20:17Z</published>
    <updated>2010-07-30T14:33:36Z</updated>

    <summary>If you do any kind of application programming, particular network oriented applications or web applications (who isn’t?), you should definitely be aware of OWASP. They keep a list of the Top Ten security concerns when developing software and I have...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
        <category term="Technology" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="development" label="development" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="internet" label="Internet" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="network" label="network" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="owasp" label="OWASP" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="security" label="security" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="software" label="software" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p>If you do any kind of application programming, particular network oriented applications or web applications (who isn&#8217;t?), you should definitely be aware of OWASP. They keep a list of the Top Ten security concerns when developing software and I have found the reference to be excellent.</p>

<ul>
<li>Site Link: <a href="http://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project">http://www.owasp.org/index.php/Category:OWASP<em>Top</em>Ten_Project</a></li>
<li>PDF Link: <a href="http://owasptop10.googlecode.com/files/OWASP%20Top%2010%20-%202010.pdf">http://owasptop10.googlecode.com/files/OWASP%20Top%2010%20-%202010.pdf</a></li>
</ul>

<p>I think a printed version of the updated Top Ten is going to become a part of my standard reference kit to look over from time to time. The guide is organized and color coded in such away that just about anyone could understand why you should be concerned and what the remedies for each of the top ten issues. It provides additional links off to further information and even a standard reference library that provides an implementation reference for best practices.</p>

<p>Cheers.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>The Danger of DWIM</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2010/07/the-danger-of-dwim.html" />
    <id>tag:contentment.org,2010://3.709</id>

    <published>2010-07-26T19:44:57Z</published>
    <updated>2010-07-26T19:44:02Z</updated>

    <summary>Perl libraries often attempt to do what you want (or DWIM, Do What I Mean) when it comes to deciding how to handle input and output. However, this can have unintended consequences if you’re not careful with these conveniences. I’m...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p>Perl libraries often attempt to do what you want (or DWIM, Do What I Mean) when it comes to deciding how to handle input and output. However, this can have unintended consequences if you&#8217;re not careful with these conveniences. I&#8217;m going to pick on an example I ran into today:</p>

<pre><code>use Data::Dumper;
use XML::Simple;
my $data = XMLin($ARGV[0]);
print Dumper($data);
</code></pre>

<p>What&#8217;s that do? It takes the input from <code>@ARGV</code> and parses it as XML, right? It returns that information as a hash, right? Maybe.</p>

<p>If this were a little script named <code>test.pl</code> and I ran this:</p>

<pre><code>./test.pl "&lt;test&gt;&lt;value&gt;foo&lt;/value&gt;&lt;/test&gt;"
</code></pre>

<p>I would end up with output of:</p>

<pre><code>$VAR1 = { value =&gt; 'foo' };
</code></pre>

<p>However, if you just ran:</p>

<pre><code>./test.pl
</code></pre>

<p>what would happen? It would try to find and open a file named <code>test.xml</code>.</p>

<p>Or I could run it like this:</p>

<pre><code>cat some.xml | ./test.pl -
</code></pre>

<p>That would cause it to read in standard input. Okay, great! That&#8217;s pretty handy, except&#8230;</p>

<p>Imagine if you were using this in a web application. Suppose you have an upload widget where someone uploads an XML file to your app and then you pass that value straight into <code>XMLin()</code> without checking, this could be very bad.</p>

<pre><code>my $xml = $c-&gt;parameters-&gt;{xml_file};
my $data = XMLin($xml);
print Dumper($data);
</code></pre>

<p>What if your user uploads a file that contains the string &#8220;/root/secret.xml&#8221; and that happens to refer to a real file that is secret?! You just passed back the information in that file.</p>

<p>Beware of the DWIM! Always check your inputs! In the case of the web app, I would recommend against any use of <code>XMLin()</code> directly and create some sort of wrapper that will only allow the input you expect:</p>

<pre><code>sub parse_xml_content { 
    my ($xml, @options) = @_;
    die 'input does not look like XML' unless $xml =~ /&lt;.*?&gt;/; 
    return XMLin($xml, @options);
}
</code></pre>

<p>This doesn&#8217;t go just for <a href="http://search.cpan.org/dist/XML-Simple/lib/XML/Simple.pm">XML::Simple</a>, but for just about anything that is smart with input.</p>

<p>Cheers.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>YAPC 2010 in Review</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2010/06/yapc-2010-in-review.html" />
    <id>tag:contentment.org,2010://3.700</id>

    <published>2010-06-26T16:06:44Z</published>
    <updated>2010-06-26T16:12:17Z</updated>

    <summary>A few days with the JAPHs has reminded me of a few things: I’m behind. I need to do a better job of keeping up with Perl things. Perl has a unique culture and community that is both interesting and...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="conference" label="conference" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="review" label="review" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="yapc" label="YAPC" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p>A few days with the JAPHs has reminded me of a few things:</p>

<ol>
<li>I&#8217;m behind. I need to do a better job of keeping up with Perl things.</li>
<li>Perl has a unique culture and community that is both interesting and valuable to what it produces.</li>
<li>I&#8217;m so glad that the people I usually hang out with do not use a certain expletive as their favorite adjective.</li>
</ol>

<p>Okay, so let&#8217;s review.</p>

<h3>Sunday</h3>

<p>I traveled to Columbus, Ohio on Sunday. My travel was mostly uneventful, other than an hour delay in Dallas to replace the brakes on the plane. Because of that, I didn&#8217;t get to have dinner with Terri&#8217;s cousins, just her uncle. However, I enjoyed a delicious meatloaf and lemonade with Keith at the <a href="http://www.capcityfinediner.com/">Cap City Diner</a> (warning the web site plays music). I arrived at <a href="http://www.theblackwell.com/">The Blackwell</a> that evening, which is apparently named after a professor at OSU who has been convicted of <a href="http://lawprofessors.typepad.com/business_law/2005/06/blackwell_convi.html">insider trading</a>. </p>

<p>My first impression of Ohio State campus is that they must have had a beautiful football stadium at one time, but now appears to be just a modern monstrosity with a beautiful arch on the end facing The Blackwell. I suppose this stadium will soon be featuring regular visits from our northern neighbors in Nebraska&#8230; I&#8217;m not an OSU fan, but I hope OSU beats NU every time they play here.</p>

<p>While traveling and late into Sunday evening, I finished up my notes for my first talk.</p>

<h3>Monday</h3>

<p>I met my <a href="http://www.grantstreet.com/">colleagues</a> in the lobby and we walked together over to the Ohio Union, where the conference was being held. The Union is knew and was a very nice place to conference, particular one priced at the value that YAPC is&#8212;though, my conference registration was paid for by the low-low price of giving two talks, which is great since I was just talking about two subjects I like to talk to others about anyway.</p>

<p><a href="http://picasaweb.google.com/lh/photo/5h7M9VGhTbqZfiqVQjaX5w?feat=embedwebsite"><img src="http://lh6.ggpht.com/_Pa_pMS-rWfY/TCLVE5QkWhI/AAAAAAAAC8A/KkFlDnLePgI/s400/2010-06-21%2008.39.36.jpg" /></a></p>

<p>The <a href="http://yapc2010.com/yn2010/talk/2751">keynote</a> on Monday was given by Jesse Vincent, who was the Perl5 v12 pumpking, which has been released and is well into it&#8217;s maintenance cycle now. For those that may not know, this marks the second major release of Perl in the last 3 years and is part of a new effort to consistently make a major release of the language every year. This is good news for at least a couple reasons.</p>

<ol>
<li>Perl language developing will stay fresher with new features coming regularly.</li>
<li>It will help dispel the message of the naysayers and show that Perl is Alive.</li>
</ol>

<p>After that, I went to a <a href="http://yapc2010.com/yn2010/talk/2653">couple</a> <a href="http://yapc2010.com/yn2010/talk/2641">talks</a> on <a href="http://www.catalystframework.org/">Catalyst</a> that I didn&#8217;t pay much attention to. This had far less to do with the quality of the talks and more to do with me thinking about my talk.</p>

<p>I gave my <a href="http://yapc2010.com/yn2010/talk/2644">first talk</a> at 10:00 am on <em>Telecommuting</em>. I will post the audio/video when Krishna gets it online. I may post the slides too, but there&#8217;s really not much to show in them. Most of it was me telling a few stories from note cards. I feel like I was a bit dull, but I got some good questions at the end, which is usually a good sign. As I said on Twitter, <a href="http://twitter.com/zostay/status/16700555654">I hope it was useful.</a></p>

<p>After breathing a sigh of relief I spent most of the rest of the day in talks and working on a project for work. I attended Util&#8217;s <a href="http://yapc2010.com/yn2010/talk/2684">talk</a> on Amazon EC2. I learned that EC2 hasn&#8217;t changed significantly since I used it. It&#8217;s still the same, though there are more instance configuration options, Windows instances, and different storage engines. This is mostly just an extension of what was there when I was last using it a couple years ago.</p>

<p>We then grabbed some lunch from <a href="http://www.theflyingpizza.com/">The Flying Pizza</a>, which was cheap and greasy and pretty good.</p>

<p>After lunch, I ended up in <a href="http://yapc2010.com/yn2010/talk/2579">Moose for Managers</a>, which wasn&#8217;t a stand-out talk in my mind since I can&#8217;t remember anything about it. However, I was working on something related to work at the time, so that&#8217;s probably just me not paying close enough attention. I stayed in the Grant Street Room to listen to Paul Fenwick&#8217;s talk on <a href="http://yapc2010.com/yn2010/talk/2902">Awesome things you&#8217;ve missed in Perl</a>. Paul is a great speaker and showed a number of things I&#8217;ve put on my todo list to investigate.</p>

<p>I ended the regular talks for the day by attending Dave Rolsky&#8217;s talk on <a href="http://search.cpan.org/dist/Fey/">Fey</a> and <a href="http://search.cpan.org/dist/Fey-ORM/">Fey::ORM</a>, which I&#8217;m mildly curious about since I once tried to write an ORM and because Fey seems like something which could be useful for something at work. By the way, my attempt at an ORM was awful and Dave actually wrote a <a href="http://cpanratings.perl.org/user/autarch#296">scathing</a> review of it on <a href="http://cpanratings.perl.org/">CPAN Ratings</a>, which is part of the reason it has been <a href="http://backpan.perl.org/authors/id/H/HA/HANENKAMP/persist/">disappeared</a> from CPAN&#8230;I think that may have been my first CPAN module. Oh well. No hard feelings.</p>

<p>Finally, there were the lightning talks. They were enjoyable, as usual, but I&#8217;m not sure there are any that stand out in my mind from Monday.</p>

<p>After that, my fellow Grant Streeters headed out to dinner. We went to a local, cheap Chinese place, which was pretty decent. I stayed up late working after that, though after all the talks and travel I was pretty spent, so I got done far less than I wanted.</p>

<h3>Tuesday</h3>

<p>I ended up sleeping in a bit and missed the first round of talks and caught only the last part of Michael Schwern&#8217;s talk on the <a href="http://yapc2010.com/yn2010/talk/2709">coding cycle</a>. I stayed in the Grant Street room to see Gabor Szabo&#8217;s talk on <a href="http://yapc2010.com/yn2010/talk/2782">Padre</a>, which I&#8217;ve long been interested in, but still haven&#8217;t looked at much. If you want to learn Perl, using this editor sounds like the best way to get started.</p>

<p>Then it was lunch again, at Chipotle this time. Mmmm&#8230; <a href="http://www.chipotle.com/">Chipotle</a>.</p>

<p>I attended <a href="http://yapc2010.com/yn2010/talk/2657">scrottie&#8217;s talk</a> on running Perl in a cheap distributed computing system (i.e., a pile of cheap computers working together to form a supercomputer of sorts). This was followed by Nick Perez giving a talk on <a href="http://yapc2010.com/yn2010/talk/2640">how he&#8217;s building apps using POE and Plack</a>.</p>

<p>I moved downstairs to another Schwern talk, this time on <a href="http://yapc2010.com/yn2010/talk/2708">perl5i</a>, which is a pretty interesting project. He&#8217;s basically taken to pulling in his favorite language extensions and piled them into a single module, <a href="http://search.cpan.org/dist/perl5i/">perl5i</a>. I&#8217;m still thinking about how it works and wondering if I like it or not. I certainly like most of the modules he&#8217;s brought in and how it works. I&#8217;m just not certain I like the <code>mo</code> and <code>mc</code> meta-accessors&#8230; still considering it.</p>

<p>After that talk, I stepped out for a while and worked a bit and chatted with some folks in the lobby of the Union. I met a lot of great folks while here, too many to mention all of them.</p>

<p>Then, I attended the <a href="http://yapc2010.com/yn2010/talk/2666">keynote</a>, which was given by Stevan Little. This talk explored the history of Perl and how we got to Modern Perl today. Using some concepts by Larry Wall, he wanted to show how Perl had filled a void that once existed in Unix. That is, it used to be if you wanted manipulexity (lots of deep functionality) you wrote something in C. If you needed something with whipuptitude (built quickly and easily) you used shell script. Perl was an attempt to fill in the difference so you could have both manipulexity and whipuptitude. Modern Perl is the outcome and successful implementation of this.</p>

<p><a href="http://picasaweb.google.com/lh/photo/inOj5KW5vStMji4vp7juRg?feat=embedwebsite"><img src="http://lh3.ggpht.com/_Pa_pMS-rWfY/TCLV3QXn0xI/AAAAAAAAC8Q/UZf3cuPNAPM/s400/2010-06-22%2017.01.57.jpg" /></a></p>

<p>This is also a good opportunity to explain that while Perl has long had the slogan TMTOWTDI (There&#8217;s More Than One Way To Do It) from Larry Wall, Modern Perl makes it longer with <a href="http://twitter.com/zostay/status/16798370400">TMTOWTDI BSCINABTE</a>. This is pronounced Tim Toady Bicarbonate, which acronymizes, &#8220;There&#8217;s More Than One Way To Do It But Sometimes Consistency Is Not A Bad Thing Either.&#8221; This is an extension to Perl thinking that basically adds a little more consistency to programming (via Moose and related thinking) without actually losing any flexibility. (In fact, Modern Perl is really much more flexible in many ways, it just adds a common foundation that makes that flexibility a little more solid and less re-inventive.)</p>

<p>After this came the second round of lightning talks. There were again several good ones, but I think the talk that outshined them all was the one by Makoto Nozaki titled &#8220;<a href="http://yapc2010.com/yn2010/talk/2693">How I mastered English with Perl</a>.&#8221; It was great. I hope the video of it is posted so I can watch it again.</p>

<p>After this, we had the banquet, where I sat with one of my coworkers, Dieter, some of the folks from <a href="http://bestpractical.com/">Best Practical</a> (Shawn Moore, Kevin Falcone, and Jesse Vincent) and got to meet a couple others, Elliot and Ingy. I had a pretty decent time learning a bit about others, talking with Elliot and Jonathan Rockway in the food line, and made a smallish bid on some coasters during the auction. Pathetic, I know, but I did by a new Perl T-shirt since my Perl polo I bought at OSCON is starting to wear.</p>

<p><a href="http://picasaweb.google.com/lh/photo/5__404dWwP5z75lydlTNHw?feat=embedwebsite"><img src="http://lh3.ggpht.com/_Pa_pMS-rWfY/TCLUH5ot0rI/AAAAAAAAC7o/phKstRfFMno/s400/2010-06-22%2019.47.55.jpg" /></a></p>

<p>After that, I went with some folks and ended up talking about work with my coworkers at a local bar before heading back to my room where I stayed up late inventing a new talk to replace the one I wasn&#8217;t able to get together in time.</p>

<h3>Wednesday</h3>

<p>I started the morning by attending another <a href="http://yapc2010.com/yn2010/talk/2710">Schwern talk</a> on <a href="http://github.com/gitpan">gitPAN</a>, which is a really cool way of mining information about CPAN using <a href="http://github.com">github</a>. This was followed by a talk by Tatsuhiko Miyagawa on <a href="http://yapc2010.com/yn2010/talk/2601">cpanminus</a>, which I had only heard rumors of up until this point. Now that I&#8217;ve tried it out, I&#8217;m not sure why I haven&#8217;t been using it for months now. It&#8217;s a very nice (simple!) CPAN client that handles most of what you need when you just want to install a module to try it out.</p>

<p>I then gave my second and <a href="http://yapc2010.com/yn2010/talk/2592">final talk</a> on <a href="http://search.cpan.org/dist/Form-Factory/">Form::Factory</a>, which showed a bit on how to extend Moose and how I like to build forms, but I don&#8217;t think it&#8217;s earth shattering. I would like it to be, but my time to hack is constrained by so many things.</p>

<p>I followed that with mst&#8217;s talk on <a href="http://yapc2010.com/yn2010/talk/2627">The Troll, the God, and the Mountain</a>, which was a very unusual introduction to <a href="http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=dbsrgits/DBIx-Data-Store.git;a=summary">DBIx::Data::Store</a>. The punchline is that the Troll, Thog and his friend Al, are renamed and made great by the god v10 (&#8220;Voton,&#8221; i.e., Perl 8 v10) to become &#8220;Orthog-an-Al Persisten-T roles.&#8221; That&#8217;s about all I remember, to be honest. I&#8217;ve been hearing a few rumors about this project via Rob Kinyon (I think), though, so I&#8217;m keeping an eye open for when it hits CPAN.</p>

<p><a href="http://picasaweb.google.com/lh/photo/70IMcCNLpUbFTUIpQriudg?feat=embedwebsite"><img src="http://lh5.ggpht.com/_Pa_pMS-rWfY/TCLXGGKCLSI/AAAAAAAAC8w/hjpQPf0qpaE/s400/2010-06-23%2011.19.34.jpg" /></a></p>

<p>I had one more lunch at YAPC, with a bunch of folks I didn&#8217;t know and Rob. I confess to have forgotten all names at this lunch, but they were good company for lunch.</p>

<p>Next, I attended <a href="http://yapc2010.com/yn2010/talk/2686">Cool Perl 6 today</a> by Patrick Michaud, who is the lead on Rakudo, which is the engine for Perl 6. I&#8217;m really thinking Perl 6 should be renamed to something else because it&#8217;s like Perl, but it&#8217;s not Perl. I like to watch these talks mostly for fun, though, things are getting to the point now that you can write Perl 6 applications, which is tempting to try.</p>

<p>I then attended a really excellent talk on autodie, titled &#8220;<a href="http://yapc2010.com/yn2010/talk/2903">The Art of Klingon Programming</a>&#8221; by Paul Fenwick. The talk featured Paul in a TNG uniform talking about his time as an exchange officer in the Klingon empire where he was testing the new universal translator. The joke is this. If you&#8217;ve programmed very much Perl, you know a common idiom is to write &#8220;open or die.&#8221; The reason is that if the file doesn&#8217;t open it returns a false value, so the short circuit &#8220;or&#8221; operator allows you to skip the die on success or run the die on failure. This is a good way to ask for blood wine in Klingon, since trying to ask nicely won&#8217;t get you any. The autodie module comes along to make this kind of talk automatic (making open die without the &#8220;or die&#8221; on the end).</p>

<p><a href="http://picasaweb.google.com/lh/photo/GENI55NlDDdEpN49BrChRQ?feat=embedwebsite"><img src="http://lh5.ggpht.com/_Pa_pMS-rWfY/TCLW6yuv3LI/AAAAAAAAC8s/9MBmF0a4URo/s400/2010-06-23%2014.02.22.jpg" /></a></p>

<p>Prior to the final keynote by mst, I attended two more Moose talks, <a href="http://yapc2010.com/yn2010/talk/2646">one</a> by doy and the <a href="http://yapc2010.com/yn2010/talk/2582">other</a> by perigrin. Both had way more information than I was really able to consume and the major thing that I took away was that I need to look into the new declarative syntax and immerse myself more deeply into the Moose type system, which I&#8217;ve really barely touched.</p>

<p>The final <a href="http://yapc2010.com/yn2010/talk/2626">keynote</a> was given by mst, which was another summary of the history of Perl as well as a general summary of some of the good things that have happened in the world of Perl in the past year.</p>

<p><a href="http://picasaweb.google.com/lh/photo/Z_cd1mBviYS7dgPoR2aA0g?feat=embedwebsite"><img src="http://lh5.ggpht.com/_Pa_pMS-rWfY/TCLUtmKAJ4I/AAAAAAAAC70/jfmRCa_wl6Q/s400/2010-06-23%2019.51.12.jpg" /></a></p>

<p>After that, I went over to the <a href="http://www.bluenilecolumbus.com/">Blue Nile Ethiopian Restaurant</a> with the other speakers (and hangers on) and experienced my first taste of Ethiopian food and had one more social event. I got to speak a bit with chromatic, whom had edited the articles O&#8217;Reilly published to OnLamp. I got to chat with Ricardo Signes, Dave Rolsky,  Rob&#8217;s wife, Randall Schwartz, and several others. It was a good time.</p>

<p><a href="http://picasaweb.google.com/lh/photo/_ZcoBM-1Fb0E_Qe81oHyjw?feat=embedwebsite"><img src="http://lh3.ggpht.com/_Pa_pMS-rWfY/TCLUidn3XDI/AAAAAAAAC7w/LQO2QbopmU0/s400/2010-06-23%2019.50.23.jpg" /></a></p>

<p>Finally, it was time to pack and head home.</p>

<h3>In Summary</h3>

<p>Perl has a really interesting culture. Between the libraries on CPAN, the dedication of many developers to the language and the community, and the way the leaders in the community interact with it, Perl has a lot going for it. It almost seems like there is a bit of religious fervor to it, though, that&#8217;s partially just the concentration of people getting together to talk about Perl. Most of these folks work in other languages too and have important concerns outside of Perl.</p>

<p>On my list of things I need to look into from the conference:</p>

<ul>
<li><a href="http://search.cpan.org/dist/App-perlbrew/">Perlbrew</a>: A nice way of installing Perl VMs for development and testing.</li>
<li><a href="http://search.cpan.org/dist/local-lib/">local::lib</a>: A nice way of locating and using CPAN modules installed to your home directory.</li>
<li><a href="http://search.cpan.org/dist/App-cpanminus/">cpanminus</a>: A tool that simplifies installing modules from CPAN.</li>
<li><a href="http://search.cpan.org/dist/Bread-Board/">Bread::Board</a>: A framework for inversion of control, which is something I want to do better with in Form::Factory</li>
<li><a href="http://cpan-explorer.org/">CPAN Explorer</a>: A visualization of CPAN.</li>
<li><a href="http://search.cpan.org/dist/Reflex/">Reflex</a>: A new syntax for doing POE-like things with Moose.</li>
</ul>

<p>There are others, but I don&#8217;t want the list to get too long.</p>

<p>Anyway, that&#8217;s my summary of everything I have to say about YAPC::NA 2010. Lord willing, I hope to attend again.</p>

<p>Cheers.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Samsung Moment: Best Phone I Ever Had</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2010/06/samsung-moment-best-phone-i-ev.html" />
    <id>tag:contentment.org,2010://3.697</id>

    <published>2010-06-03T23:00:00Z</published>
    <updated>2010-06-03T15:11:29Z</updated>

    <summary>I have no idea how this phone compares to other Android-based phones. I’m not going to compare it. However, compared to the Motorola Q9c running Windows Mobile, the Treo running Palm OS, and the Nokia 3650 running Symbian, this is...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p>I have no idea how this phone compares to other Android-based phones. I&#8217;m not going to compare it. However, compared to the <a href="http://www.motorola.com/Consumers/US-EN/Consumer-Product-and-Services/Mobile-Phones/MOTO-Q-9c-US-EN">Motorola Q9c</a> running <a href="http://www.microsoft.com/windowsmobile/en-us/default.mspx">Windows Mobile</a>, the Treo running Palm OS, and the <a href="http://en.wikipedia.org/wiki/Nokia_3600/3650">Nokia 3650</a> running Symbian, this is clearly the best phone I&#8217;ve owned. I&#8217;ve now been using it for a couple months and I still make good use of it on a daily basis. I think it of it more as a small laptop than as a cell phone. I can definitely see what the appeal is for having a tablet like this with a larger screen now. My next laptop may be one of these mini-laptop/tablets running Android I see coming out soon.</p>

<p>So far the only downside has been the battery life, which is mostly a problem when I travel. However, I can use my mini laptop (with it&#8217;s very nice 6-cell battery) as a charger. The other downside I experienced was that Sprint installs a bunch of apps I don&#8217;t need or want running in the background. However, since I rooted the phone, I&#8217;ve solved that problem rather nicely and have extended my battery life a bit in the process.</p>

<p>One of the main thing that makes Android nice is all the apps. So, I&#8217;m going to list my favorite apps now. I have added <a href="http://en.wikipedia.org/wiki/QR_Code">QR codes</a> to each in the Android Market, so you can get to them easily if you have a barcode scanner on your phone. If you don&#8217;t, I recommend ShopSavvy below or Barcode Scanner also works.</p>

<h3>Auto Memory Manager</h3>

<p><img alt="QR code to Auto Memory Manager" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.lim.android.automemman" width="120" height="120" class="mt-image-right" style="float: right; margin: 0;" /></p>

<p>By <a href="http://madsquirrelapps.wordpress.com/">Mad Squirrel</a>. This app is, on it&#8217;s own, worth the effort of rooting your phone. Android allows you to run multiple apps at once. You can see the last 6 or so such apps by holding down the Home key. When too many apps are running, Android will kill of the lowest priority ones to keep the phone from getting too hot and running down the battery. Sometimes this isn&#8217;t aggressive enough.</p>

<p>There are apps you can get (such as the EStrongs Task Manager) that will kill off running apps on top of the built-in task manager, but why run an app to do that when you can just adjust the built-in one? That&#8217;s what Auto Memory Manager does. It lets you tweak the settings of the built-in task manager. You need root to your phone to do it, but it&#8217;s worth it. I keep AMM on the minimum settings (only slightly more aggressive than the factory settings) and it makes a big difference.</p>

<h3>LauncherPro</h3>

<p><img alt="QR code to LauncherPro Beta" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.fede.launcher" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.launcherpro.com/">Federico Carnales</a>. Android&#8217;s equivalent to the Start Menu is the launcher menu. It&#8217;s a little drawer you slide up with your finger from the bottom. The built in one is kind of boring. LauncherPro replaces this with one that gives you customizable buttons at the bottom and gives you the option to have a larger home screen. The animations and such are very smooth and I think it brings up the menu faster than the built-in one.</p>

<h3>Bible (YouVersion)</h3>

<p><img alt="QR code to Bible" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.sirma.mobile.bible.android" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.youversion.com/">LifeChurch.tv</a>. This is one of the two Bible programs I have installed. This one uses the Internet connection to pull Bible verses from online servers. I don&#8217;t like the reader as much as the one from Olive Tree, but it has some nice reading plan helpers that I use.</p>

<h3>ESV for BibleReader</h3>

<p><img alt="QR code to ESV for BibleReader" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:esv.biblereader.olivetree" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.olivetree.com/">Olive Tree BibleReader</a>. This is a full blown Bible study program for the phone. I paid $10 for the <a href="http://esv.org">ESV</a> version, which is now installed on the phone directly. You can also purchase additional books and study helps if you chooes. I&#8217;ve installed a few of the free ones. Navigating the Bible is very easy with this and the text is nicely formatted. The main downside is navigating any other text is not easy and it has a few rough edges, like not remembering what you were last looking at if you don&#8217;t quit through the menu and the bookmarks are nearly useless.</p>

<h3>WeatherBug Elite</h3>

<p><img alt="QR code to Weatherbug Elite" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.aws.android.elite" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://weather.weatherbug.com/mobile/android.html">WeatherBug Mobile</a>. I&#8217;ve tried <a href="http://weather.com">Weather.com</a> (which comes with the phone) and <a href="http://accuweather.com">AccuWeather</a> and WeatherBug and WeatherBug wins, easily, as the best weather app and widget set. I can now get a nice weather map on my home screen, the current conditions, and 2 day forecast at a glimpse. It also keeps the current temp up in the corner, which is nice. This one is less quirky than the other weather apps I&#8217;ve tried too. It was easily worth the $3 I paid for the version without ads and the extra widgets.</p>

<h3>ColorDict Dictionary</h3>

<p><img alt="QR code to ColorDict Dictionary" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.socialnmobile.colordict" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.socialnmobile.com/">Notes</a>. I&#8217;m a word geek. I look up words in the dictionary almost daily. This provides a dictionary installed on the phone so it works even if I don&#8217;t have a connection. It has a variety dictionaries available and a <a href="http://wikipedia.org">Wikipedia</a> add-on that will look things up there when the Internet connection is available.</p>

<h3>K-9 Mail</h3>

<p><img alt="QR code to K-9 Mail" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.fsck.k9" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://k9mail.googlecode.com/">K-9 Dog Walkers</a>. Best IMAP mail reader on Android. This was the only app I knew about before I got an Android phone. One of my Perl-geek acquaintances, <a href="http://fsck.com">Jesse Vincent</a>, wrote this to replace the built-in Mail app. It is very configurable and much nicer in nearly every way than the built-in IMAP mail program. I didn&#8217;t like some features of it at first until I learned that I&#8217;d just missed one of the settings screens.</p>

<h3>Google Voice</h3>

<p><img alt="QR code to Google Voice" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.google.android.apps.googlevoice" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://gesturesearch.googlelabs.com/">Google Inc.</a> This is another excellent app for Android. This allows me to send all of my calls from my phone through my <a href="http://voice.google.com">Google Voice</a> account automatically. I already use this for voicemail, so I get my voicemail online and I get a reasonably useful text transcript of the voicemail. And that&#8217;s just some of the features.</p>

<h3>AnyPost</h3>

<p><img alt="QR code to AnyPost" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.skamped.anyposts" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.skamped.com/anypost">skAmped</a>. I use this to send pictures and status updates to Twitter and <a href="http://facebook.com">Facebook</a> from my phone. It connects to <a href="http://ping.fm">ping.fm</a>. I prefer it to the <a href="http://hootsuite.com">Hootsuite</a> App (which still only does <a href="http://twitter.com">Twitter</a>) and just about anything else I&#8217;ve tried. This app is very simple and just does what it needs. Good enough.</p>

<h3>Dolphin Browser HD</h3>

<p><img alt="QR code to Dolphin Browser HD" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:mobi.mgeek.TunnyBrowser" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://home.dolphin-browser.com/tunny/Home.htm">Dolphin Browser</a>. This is a new browser for the phone. The built-in browser is fine, but this one just adds a few extras that make it worth it. For example, with an add-on it will save bookmarks to the SD card so that you won&#8217;t lose them when you do an OS update or get the phone repaired.</p>

<h3>Google Maps / Navigation</h3>

<p><img alt="QR code to Google Maps" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.google.android.apps.maps" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://gesturesearch.googlelabs.com/">Google Inc.</a> The phone comes with Sprint Navigation. That application does the job, barely. Google Maps with Navigation does the job well, very well. I bought a dash-mount to put into the van because this app actually works to navigate me. With Sprint Navigation, I was always waiting forever for it to finish loading the route from the online service and if it thought you got off track (which is inevitable with the weak GPS chips in these phones) it would lock up trying to reroute. Google Navigation loads the map and then is smart enough to reroute in a second or two on it&#8217;s own without contact the server again.</p>

<h3>Genial Writing</h3>

<p><img alt="QR code to Genial Writing" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.zenpie.genialwriting" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://zenpie.blogspot.com/">zenpie studio</a>. When I first downloaded this app, I just wanted to see what it was since it looked interesting. Now, I use it to take notes more often than my other note taker app. It lets you take notes using your own &#8220;handwriting.&#8221; This is very appealing for a number of reasons. This is a purely emotionally satisfying solution, even though it lacks certain practical features like being able to search (how can it search when all it does is record your writing). I still recommend it. It&#8217;s fun to use.</p>

<h3>ColorNote Notepad</h3>

<p><img alt="QR code to ColorNote Notepad" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.socialnmobile.dictapps.notepad.color.note" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.socialnmobile.com/">Notes</a>. This is my favorite general note taker app. I use it for shopping lists and reminders that I want posted to the home screen. It&#8217;s handy.</p>

<h3>Handcent SMS</h3>

<p><img alt="QR code to Handcent SMS" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.handcent.nextsms" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.handcent.com/">handcent_admin</a>. I&#8217;m not totally sold on this app yet. It adds a bunch of extra junk that isn&#8217;t related to SMS (font packs, it&#8217;s own voice input, it&#8217;s own notification system, etc.) I also find the default colors and theming to be very ugly. I didn&#8217;t buy an iPhone and I don&#8217;t really think apps on my phone need to look like one.</p>

<p>It is an improvement over the built-in SMS Messenger in some small ways, like the fact that it gives you a popup for quick replies and lets you do some nice per-contact customizations.</p>

<h3>StopWatch</h3>

<p><img alt="QR code to StopWatch" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.sportstracklive.stopwatch" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://sportstracklive.com/">sportstracklive.com</a>. I use this for lots of things. If I need to time something or if I need a countdown to something (like Terri has asked me to take something out of the oven), this is a very nice app. It has a nice large timer display, allows for multiple countdowns, and has a button for recording laps (which I mostly use to help me track time while grilling).</p>

<h3>Droid48</h3>

<p><img alt="QR code to Droid48" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:org.ab.x48" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By [shagrath])(http://twitter.com/shagr4th). The <a href="http://en.wikipedia.org/wiki/HP-48_series">HP 48</a> is the Best. Calculator. Ever. This provides the classic calculator with <a href="http://en.wikipedia.org/wiki/Reverse_Polish_notation">RPN</a> and everything. I wish it handled the (real) keyboard a little better, but I like the app anyway.</p>

<h3>Congress</h3>

<p><img alt="QR code to Congress" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.sunlightlabs.android.congress" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://sunlightlabs.com/">Sunlight Labs</a>. This is a beautiful app for keeping track of what your local Congressmen (or anyone&#8217;s Congressmen) are up to. It provides news about them, easy access to their Twitter and <a href="http://youtube.com">Youtube</a> feeds, and information about bills they are currently sponsoring. If you want to stay up to date on national politics, this is great.</p>

<h3>EStrongs File Explorer</h3>

<p><img alt="QR code to EStrongs File Explorer" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.estrongs.android.pop" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.estrongs.com/">EStrongs</a>. I&#8217;ve tried a few different SD card browsers and this is probably my favorite, though Astro is a close second.</p>

<h3>EStrongs Task Manager</h3>

<p>By <a href="http://www.estrongs.com/">EStrongs</a>. This is the task manager that goes with the file browser. It&#8217;s pretty standard and I use it to kill off apps every now and then.</p>

<h3>ConnectBot</h3>

<p><img alt="QR code to ConnectBot" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:org.connectbot" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://connectbot.org/">Kenny Root and Jeffrey Sharkey</a>. Gives you a terminal on the local machine (i.e., on the phone) so I can execute Linux programs and such locally. It also gives me SSH in case I need to manage one of my servers.</p>

<h3>TripIt - Travel Organizer</h3>

<p><img alt="QR code to TripIt" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.tripit" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.tripit.com/">TripIt, Inc.</a> I organize all my trip itineraries on TripIt.com. This brings the web site to my phone, which is very helpful on occasion when I need to remember where I&#8217;m going, what my confirmation numbers are, or whatever.</p>

<h3>Twitter</h3>

<p><img alt="QR code to Twitter" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.twitter.android" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://twitter.com/">Twitter, Inc.</a> The official <a href="http://twitter.com">Twitter</a> app is better for checking <a href="http://twitter.com/zostay">my Twitter account</a> and getting updates when someone mentions me than anything else I&#8217;ve tried. It works really well, actually. I wish the Facebook app was half as nice.</p>

<h3>ShopSavvy</h3>

<p><img alt="QR code to ShopSavvy" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.biggu.shopsavvy" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.biggu.com/">Big In Japan, Inc.</a> This is the best bar code reader and shopping helper I&#8217;ve found for Android. It&#8217;s better than Google Shopper. You can use it to enter a search for a product or scan a bar code and then it will search online for Internet stores and local shops that have it and help you compare prices. Very nice.</p>

<h3>Aldiko Book Reader</h3>

<p><img alt="QR code to Aldiko" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.aldiko.android" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.aldiko.com/">Aldiko Limited</a>. I don&#8217;t have a ton of e-books, but this has a nice library of public domain books, many of which are on my list of books I want to read. Currently, I&#8217;m reading <em>Alice in Wonderland</em>. This has a very nice interface and works well. I wish the Bible readers I had worked like this app does.</p>

<h3>AndChat</h3>

<p><img alt="QR code to AndChat" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:net.andchat" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.andchat.net/">Al. R.</a> This is an IRC client. It works very well. I don&#8217;t use it quite as often as I would like to, but it is a good client in addition to my usual lurker connection (I log a number of IRC channels that I rarely interact with anymore).</p>

<h3>eBuddy Messenger</h3>

<p><img alt="QR code to eBuddy Messenger" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.ebuddy.android" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.ebuddy.com/android/">eBuddy</a>. This is a decent IM client. I do not like the user interface of this one as much as the Meebo IM client. However, it does not use up battery like Meebo does and Meebo does not seem to maintain the Android app very well.</p>

<h3>Movies</h3>

<p><img alt="QR code to Movies" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:net.flixster.android" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://flixster.com/">Flixster Inc.</a> I use this to help organize our Netflix account and check for movies in the unusual case I&#8217;m actually thinking of going to one. This actually provides a nicer interface to Netflix than the Netflix web site (which is what I say about just about every alternative web site for accessing Netflix since I find the main web site of Netflix to be impossible to navigate).</p>

<h3>Facebook for Android</h3>

<p><img alt="QR code to Facebook" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.facebook.katana" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.facebook.com/apps/application.php?id=74769995908">Facebook</a>. This is the official <a href="http://facebook.com">Facebook</a> app. I use it because it&#8217;s about the best there is, but it&#8217;s pretty bad. The notifications work every month or so. The UI uses a home page rather than the more usual menu or tab-based navigation. Clicking on notifications (when they come) or on many of the links within the app take you to the Facebook web site in the browser instead of the screen that exists within the app. When it takes you to the web site, it doesn&#8217;t even take you to the touch-site (the one made for iPhones and Android, etc.), but to the standard mobile site.</p>

<h3>Robo Defense</h3>

<p><img alt="QR code to Robo Defense" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.magicwach.rdefense" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://lupislabs.blogspot.com/">Lupis Labs Software</a>. This was the first game I tried on the phone and the one I&#8217;ve liked the best. It is extremely repetitive, but I&#8217;ve enjoyed in anyway. You have to protect one or more gates to your base by placing defense towers around it. Each game has 100 waves to it that steadily get harder. The thing that made me keep playing is that there are number of achievements you can get for doing certain things and you use points earned to buy upgrades. I&#8217;ve mostly exhausted these, so I haven&#8217;t played much recently, but it was a fun game.</p>

<h3>Blow Up</h3>

<p><img alt="QR code to Blow Up" src="http://chart.apis.google.com/chart?cht=qr&amp;chs=120x120&amp;chl=market://search?q=pname:com.camelgames.blowup" width="120" height="120" class="mt-image-right" style="clear: right; float: right; margin: 0;" /></p>

<p>By <a href="http://www.waitforcamelgames.com/">Camel Games</a>. This is another fun game. In this game, there are little stick buildings that you blow up with dynamite. The goal is to get all the pieces to settle in as small a heap as possible. In addition, you have a stuffed panda that you need to get to fall toward a certain spot on each level. Gabe likes to push the button that causes the dynamite to blow and especially likes it if I put the dynamite on the panda and blow it up.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>YAPC 2010 Telecommute Talk</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2010/05/yapc-2010-telecommute-talk.html" />
    <id>tag:contentment.org,2010://3.693</id>

    <published>2010-05-13T02:25:14Z</published>
    <updated>2010-05-13T02:30:44Z</updated>

    <summary>Help! Help! I need help! I’m giving a talk at YAPC 2010 on telecommuting as a software developer. For the talk to be successful, I’m going to need more than just my own experience to pull from. If you are...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Talks" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="help" label="help" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="survey" label="survey" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="talk" label="talk" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="telecommute" label="telecommute" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="work" label="work" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p>Help! Help! I need help!</p>

<p>I&#8217;m giving a talk at <a href="http://yapc2010.com/yn2010/">YAPC 2010</a> on telecommuting as a software developer. For the talk to be successful, I&#8217;m going to need more than just my own experience to pull from. If you are a telecommuter and have a moment, I would appreciate your help in filling out this survey.</p>

<p>The goal of the <a href="http://yapc2010.com/yn2010/talk/2644">talk</a> is two-fold:</p>

<ol>
<li>I want to explain the benefits and risks of telecommuting as a Perl developer.</li>
<li>I want to provide some practical tips to help fellow telecommuters.</li>
</ol>

<p>I want the format to be oriented towards telling a number of stories about telecommuters with practical advice interspersed.</p>

<p><a href="http://ow.ly/1KpNr">Perl Telecommute Survey</a></p>
]]>
        

    </content>
</entry>

<entry>
    <title>Books are Better</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2009/12/books-are-better.html" />
    <id>tag:contentment.org,2009://3.677</id>

    <published>2009-12-20T22:08:22Z</published>
    <updated>2009-12-20T22:45:58Z</updated>

    <summary>I was asked the other day why I prefer real paper books over electronic books the other day and realized I’d never really posted on this subject, which I feel somewhat strongly about. I have a fundamental distrust of computers...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
        <category term="Technology" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="book" label="book" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="computer" label="computer" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="data" label="data" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="digital" label="digital" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="print" label="print" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p>I was asked the other day why I prefer real paper books over electronic books the other day and realized I&#8217;d never really posted on this subject, which I feel somewhat strongly about. I have a fundamental distrust of computers and technology. That may seem a little odd coming from a software developer, but the more I learn about software development, the more this distrust grows. When it comes to books and printed materials, I can condense this distrust into three basic problems:</p>

<ol>
<li>Digital technology changes too much.</li>
<li>Digitized data is fragile and transient.</li>
<li>Digital printing is not self-sufficient.</li>
</ol>

<h3>Ever-Changing Technology</h3>

<p>Ever tried to open a document you created 10 or 20 or 30 years ago? Did you succeed? Chances are you didn&#8217;t. Ten years ago, data was saved on 3.5&#8221; floppy disks or a CD-R if you had the money for a burner. (The USB drive didn&#8217;t come into being until 2000.) Do you even have a 3.5&#8221; floppy disk drive in your house? Is the disk or CD-R even readable anymore (since the usual half-life of such things has already past)?</p>

<p>Twenty years ago, you would have used a 3.5&#8221; or 5.25&#8221; disk. Have you even seen a 5.25&#8221; drive in the past 10 years?</p>

<p>Thirty years ago, you would have used&#8230; who knows what. I was two years old. I&#8217;d have to look at Wikipedia to even get a good guess going. Audio cassettes on your Atari? Yeah, like you have something to read one of those.</p>

<p>Even if you read the media, do you have a program that works anymore to read the format? Do you have something that will read whatever word processor you had then? This is possible and maybe even likely, but even so there&#8217;s the risk it won&#8217;t work or you don&#8217;t have one. Formats change. Programs must be made to read a format. If you don&#8217;t have any such program, you might be able to get it to someone who can extra something out of it, but it&#8217;s probably gone.</p>

<p>However, I can pick up a book from any of those eras and read them today. A notebook, a journal, a magazine, a newspaper are all quite readable with modern day technology. If you printed your document and placed it somewhere dry and clean, you can still read it.</p>

<h3>Fragile and Transient</h3>

<p>I already mentioned that the old media fails rather frequently, but it gets worse. Digital data is, by necessity, encoded in an unnatural way. That is, digital data is very robust and easy to process is many ways, but the way we choose to represent digital data is made up.</p>

<p>To demonstrate this problem, let&#8217;s consider a manuscript that someone finds in the desert from 2,000 years ago. Let&#8217;s say that it&#8217;s in a script that no one has ever seen before, will it be understood? Actually, it might be. If that script happens to be similar enough to a known script, a linguist might be able to extrapolate at least something about the contents of the document. All languages and scripts are related, even constructed languages like Esperanto.</p>

<p>Now, imagine the same scenario 2,000 years in the future. Someone picks up a magnetic tape that still has some good sections on it. In the future, they know something about ASCII encoding, but not some of the other encodings that were used today. This one is one of those other encodings. They&#8217;d have to use some sort of statistically analysis and hope it&#8217;s written in a language they know with text strings they can find or something. They&#8217;re going to have a much harder time of it reconstructing the data.</p>

<p>Digital formats add another layer of encoding upon already encoded information. Usually multiple layers of encoding are involved. This makes maintenance and upkeep much higher than for books.</p>

<p>A printed book&#8217;s encodings are just the script and language it&#8217;s in without the extra layers of encoding, file formats, compression, etc. Digital data has many more things to fail along the way to prevent easy reading in the future.</p>

<h3>Self-Insufficient</h3>

<p>This is really the most important reason I like books. I can pick one off the shelf, open it to a page, and immediately examine it&#8217;s contents. If I have a book in my computer, I have to boot the computer, load the right program for reading it, and read it. If I put it on a flash drive or SD card, I have the full contents of the text with me, but I can&#8217;t do anything with it until I get a computer or cell phone or a Kindle or something capable of showing me the data.</p>

<p>A book requires no translator or reader to explain it to me. It requires no special equipment to read other than my hands and eyes.</p>

<p>In the end, a book is something I am sure I can pass on to my children as their inheritance or share with someone else without any additional effort. I rarely have that kind of guarantee when sharing a digital file or something. The digital copy of a book gives me the ability to search or process data in it, but if I just want to read, reference, or consume the content of a book, the printed page is always better.</p>

<p>Cheers.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Form Factory: A Better Way (I Think)</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2009/12/form-factory-a-better-way-i-th.html" />
    <id>tag:contentment.org,2009://3.676</id>

    <published>2009-12-09T17:53:33Z</published>
    <updated>2009-12-11T05:05:13Z</updated>

    <summary>Recently, I’ve started backing away from Jifty as my web framework of favor. There are a few reasons for this, but mostly it’s related to performance. Jifty is includes everything, Ajax, dispatch, ORM, Comet/PubSub, REST, forms, HTML, templating, and a...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
        <category term="Perl" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="catalyst" label="Catalyst" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="formfactory" label="Form::Factory" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="moose" label="Moose" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="qublog" label="Qublog" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p>Recently, I&#8217;ve started backing away from <a href="http://jifty.org">Jifty</a> as my web framework of favor. There are a few reasons for this, but mostly it&#8217;s related to performance. Jifty is includes everything, Ajax, dispatch, ORM, Comet/PubSub, REST, forms, HTML, templating, and a pony (probably a kitchen sink too). Basically, with Jifty you don&#8217;t need to spend very much time working on building up your own utilities or framework upon framework to fit your style or needs. Jifty hands you a style as well, one that I mostly like. </p>

<p>However, the cost to performance on my <a href="http://qublog.net">Qublog</a> project was too much. It was easier for me to port it to Catalyst sans-Ajax than it was to try and correct the performance issues. In addition, I no longer use Jifty for work, wanted to use features of DBIx::Class, Moose, etc. I&#8217;m not trying to bag on Jifty here, just explain why I&#8217;m moving away from it general. I very well may find a use for it for something in the future.</p>

<p>There is, however, a major feature of Jifty I miss after having moved to Catalyst. Jifty has a collection of classes for encapsulating form rendering and processing. At the center of this is the action class, which is really a glorified functor, but with all the accoutrement required to render an HTML form and to clean up, verify, and process submission. I like this. I like this a lot. I decided to use the flexibility afforded by Moose with an implementation of something like these action classes to create a new form handling system. Over my Thanksgiving vacation, I was able to build up what has become Form::Factory.</p>

<h3>An Example</h3>

<p>Okay, I thought about showing you the process I worked through to get here, but you probably want to see it in action first. I&#8217;ll work backwards from there.</p>

<p>In order to use Form::Factory, you must first define an action class. Here&#8217;s a simple login action you might use to present a login form to your users in a web application:</p>

<pre><code>package MyApp::Action::Login;
use Form::Factory::Processor;

has_control login_name =&gt; (
    control =&gt; 'text',
    features =&gt; {
        required =&gt; 1,
        trim =&gt; 1,
        length =&gt; {
            minimum =&gt; 3,
            maximum =&gt; 20,
        },
        match_regex =&gt; {
            regex =&gt; qr{.@.}, # really naive check for email address-ish thing
            message =&gt; qw{your %s should be an email address},
        },
    },
);

has_control password =&gt; (
    control =&gt; 'password',
    features =&gt; {
        required =&gt; 1,
        trim =&gt; 1,
    },
);

has c =&gt; (
    is =&gt; 'ro',
    isa =&gt; 'MyApp',
    required =&gt; 1,
);

sub run {
    my $self = shift;

    if ($self-&gt;c-&gt;authenticate({ name =&gt; $self-&gt;login_name, password =&gt; $self-&gt;password })) {
        $self-&gt;result-&gt;success("welcome back,  @{[$self-&gt;login_name]}!");
    }
    else {
        $self-&gt;result-&gt;failure('the login name and password you entered is wrong');
    }
}
</code></pre>

<p>The <code>has_control</code> calls establish the inputs expected for our login action and tell the action what features those controls have. For example, the <code>required</code> features will result in a form that reports an error for that control when no value is given during a submission.</p>

<p>The <code>run</code> method here actually performs the action. (For this example, I&#8217;m using something Catalyst-ish, but this could just as easily be used with CGI, CGI::Application, Plack, Jifty, or whatever you prefer.)</p>

<p>To use the login action in our web application, we&#8217;ll now need to send the form to the user. Here&#8217;s a Template::Declare template that should work:</p>

<pre><code>template 'user/login' =&gt; sub {
    my ($self, $c) = @_;

    page_wrapper {
        form { { action is 'user/check_login', method is 'POST' }
            my $interface = Form::Factory-&gt;new_interface(HTML =&gt; {
                renderer =&gt; sub { outs_raw(@_) },
            });
            my $action = $interface-&gt;new_action('MyApp::Action::Login', { c =&gt; $c });
            $action-&gt;unstash('login');
            $action-&gt;render;
            $action-&gt;clear_messages;
            $action-&gt;stash('login');
            $action-&gt;render_control(button =&gt; { name =&gt; 'login' });
        };
    };
};
</code></pre>

<p>That would render an HTML form that the user can then fill in and submit. The <code>new_interface</code> call creates an instance of an interface class. These are responsible for connecting an object to the user interface. In this case, it&#8217;s an HTML form. </p>

<p>The <code>new_action</code> call then creates an instance of the action class associated with our interface class. Note that we can pass a hashref of arguments that will be passed to the constructor.</p>

<p>The <code>unstash</code> and <code>stash</code> calls are handy for remembering certain things about the form. This includes any error or success messages associated with processing the form. For example, if the user entered their login name, but the incorrect password. The processing bit (which we&#8217;ll see in a moment) would stash the error from trying to authenticate and would also stash the login name itself (but not the password since passwords controls don&#8217;t ask to stash their value). Then, when the form draws again, teh error message will be shown and the login name box will come prefilled with the previous entry.</p>

<p>The <code>clear_messages</code> call clears the messages from the action so that we can stash a clean slate for the action (we don&#8217;t want to see a message we already displayed again).</p>

<p>The <code>render</code> method renders all the controls associated with the action. (By passing the <code>controls</code> option you can output only a subset if you wish.) The <code>render_control</code> is used to output a button that is not directly associated with the action (in this case we just use it to get the user to send the form back to us).</p>

<p>Once the user clicks on our &#8220;Login&#8221; button, we&#8217;ll then want to process the input. That looks something like this:</p>

<pre><code>sub check_user_login :Path('user/check_login') :Args(0) {
    my ($self, $c) = @_;

    my $interface = Form::Factory-&gt;new_interface('HTML');
    my $action = $interface-&gt;new_action('MyApp::Action::Login', { c =&gt; $c });
    $action-&gt;unstash('login');

    $action-&gt;consume_and_clean_and_check_and_process(
        request =&gt; $c-&gt;request-&gt;params,
    );

    if ($action-&gt;is_valid and $action-&gt;is_success) {
        $c-&gt;response-&gt;redirect('/index');
    }
    else {
        $action-&gt;stash('login');
        $c-&gt;response-&gt;redirect('/user/login');
    }
}
</code></pre>

<p>We get the interface and action objects same as before. We unstash the saved information again. Then, we do that long method, which is a shortcut for saying:</p>

<pre><code>$action-&gt;consume( request =&gt; $c-&gt;request-&gt;params );
$action-&gt;clean;
$action-&gt;check;
$action-&gt;process;
</code></pre>

<p>The <code>consume</code> method takes the input and applies that to each control object. </p>

<p>The <code>clean</code> method then cleans up the values given to each control. In this case, for example, the <code>login_name</code> will have whitespace trimmed from the beginning and end since it uses the <code>trim</code> feature.</p>

<p>The <code>check</code> method then validates the inputs to determine whether or not we can reasonably expect the user&#8217;s input to have a chance at working. Here&#8217;s where most of the features added above will do their work. If the user does not enter anything for the username, the required feature will cause the control to be set as invalid.</p>

<p>Then, the <code>process</code> method will cause the action to process. Actually, the <code>process</code> method itself first checks to see if the input is valid and does nothing if it is not. If it is valid, it will copy the values from the control objects into the action attributes and run the <code>run</code> method defined on the action.</p>

<p>Finally, we can check the success or failure of the action and react accordingly. That&#8217;s how Form::Factory works in a nutshell.</p>

<h3>Goals</h3>

<p>Now that you&#8217;ve seen an example, here&#8217;s what I want to achieve in a nutshell:</p>

<ol>
<li>Actions should be well-structured, but very simple to build.</li>
<li>Actions are tied to the user interface by controls, which are easy to extend.</li>
<li>Common features of actions should be simple to define and associate with actions.</li>
<li>User interfaces should be easy to build for hosting actions.</li>
</ol>

<h4>Actions are Well-Structured, Simple</h4>

<p>Actions are just functors, function objects. At the center of each is a <code>run</code> method responsible for taking some action. To get there, however, you need input and after you get there you need output. Form::Factory uses Moose attributes to specify what input the action takes. Each <code>has_control</code> builds an attribute onto the action, but also associates more information about how it interacts with the user.</p>

<p>The output is a little less formally specified at this point, but comes out through a result object. The result object is a list of messages associated with the action along with some status information. It can also return a hash of other information for more general output. However, I&#8217;m assuming that most of the output of the action is the side-effects the action performs.</p>

<p>When an action is run, it goes through four basic phases to process:</p>

<ol>
<li><strong>Consume.</strong> The user input is delivered to each control associated with each attribute on the action.</li>
<li><strong>Clean.</strong> The input in each control is filtered and corrected, allowing whitespace to be removed, numbers to be reformatted, etc.</li>
<li><strong>Check.</strong> The input of each control is validated and any errors discovered are reported. Processing stops here if there are errors.</li>
<li><strong>Process.</strong> The input in each control is copied into the action attributes directly and the action is run.</li>
</ol>

<p>In addition to the features attached to the controls, you can specify general subroutines which will run during these phases. For example, if you have a form for changing a password, you might want a check that looks like this:</p>

<pre><code>has_checker check_that_passwords_match =&gt; sub {
    my $self = shift;
    my $new_password = $self-&gt;controls-&gt;{new_password}-&gt;current_value;
    my $confirm_password = $self-&gt;controls-&gt;{confirm_password}-&gt;current_value;

    if ($new_password ne $confirm_password) {
        $self-&gt;result-&gt;is_valid(0);
        $self-&gt;result-&gt;error('the New Password and Confirm Passwords do not match');
    }
};
</code></pre>

<p>This allows you action&#8217;s <code>run</code> method to focus on the task it performs and nicely segments off all the checks. You can also logically group your checks and filters so that they are separate from each other. This makes it easier to subclass your actions or compose them from roles.</p>

<h4>Controls are the Bridge</h4>

<p>An attribute added to your action with <code>has_control</code> has a control object associated with it. This control does most of the work until right before processing. The control receives the initial input, the cleaned input, and is where the value sits when checked. It is not until it is checked that the value enters the attribute instance slot. </p>

<p>Without the control in place, i.e., if we assigned to the attribute directly, Moose would object to the input before we have a chance to do anything. I want to avoid exceptions in this case as well because input validation failures are not exceptional, they&#8217;re expected. We need a way to easily send back notes the user about corrections needed and would like to avoid spewing call stacks unnecessarily.</p>

<p>Controls also suggest how the user interface object should present them to the user. An interface is not bound to use these suggestion in exactly the same way as its peers. For example, a text control in HTML might just be a text input box while in a CLI interface might be presented as a command-line option that takes an argument. A check box, on the other hand, will be a check box input in HTML, but would be an option that takes no arguments in a CLI (it&#8217;s presence suggesting &#8220;on&#8221; and it&#8217;s absence suggesting &#8220;off&#8221;).</p>

<h4>Features Modify Actions</h4>

<p>A common feature of form handling is filtering and input verification. In Jifty these were called canonicalization and validation. Horrible. I&#8217;ve called them cleaning and checking. In general, though, the cleaning and checking you want to do is extremely repetitive. On almost everything I want to trim the whitespace and verify that something that is required is present. I often want to check input length for something too long or too short. Sometimes I want to check that email addresses or phone numbers are sane, etc. In Form::Factory, all of these are called &#8220;features.&#8221;</p>

<p>A feature is a generic object that modifies an action. These can be anything from a feature that is just used to flag the role for some reason to features that actually modify the structure and processing of the form. Features can also be attached to particular controls to clean or check an individual control&#8217;s input.</p>

<h4>Interfaces Talk to the User</h4>

<p>And interfaces are probably what make Form::Factory most unique. An interface looks at the controls for an object and presents them somehow to the user. Currently, I&#8217;ve written an HTML interface and a CLI interface. The HTML interface presents them using the matching HTML form controls. The CLI interface presents them as a usage snippet describing the command-line options the action accepts. You can define a single action class and use that action to define a web form or a command-line interface.</p>

<p>I plan to add a REST interface as well, which will be a variation of the HTML interface. Other interfaces I&#8217;ve considered (but have no plans for at this time) could include things like a Wx GUI, a PDF interface that builds a PDF with form fields and then consumes FDF documents created from that, an XForms interface, a XUL interface, or a curses interface.</p>

<p>Okay, so that&#8217;s my current contribution to the forms parsing arena. I&#8217;m still working the kinks out, so be careful if you give Form::Factory a try. Things will change. Otherwise, I&#8217;d love some feedback and help ironing out some of the wrinkles.</p>

<p>Cheers.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Bluga WebThumbs 1.0 for Drupal 6</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2009/11/bluga-webthumbs-10-for-drupal.html" />
    <id>tag:contentment.org,2009://3.674</id>

    <published>2009-11-04T04:02:47Z</published>
    <updated>2009-11-04T04:18:29Z</updated>

    <summary>If you use Drupal and would like to automatically generate thumbnails of web sites, you might want to take a look at the Bluga WebThumbs module. Once that module is installed on Drupal and you have given the module your...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
        <category term="Drupal" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="blugawebthumb" label="Bluga WebThumb" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="drupal" label="drupal" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="modules" label="modules" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="webservices" label="web services" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p>If you use <a href="http://drupal.org">Drupal</a> and would like to automatically generate thumbnails of web sites, you might want to take a look at the Bluga WebThumbs <a href="http://drupal.org/project/bluga">module</a>. Once that module is installed on Drupal and you have given the module your <a href="http://webthumb.bluga.net/home">Bluga WebThumb</a> API key, you can then inject a PHP snippet like this into a node using the PHP filter or into a theme file:</p>

<pre><code>&lt;?php
print bluga_webthumb('http://contentment.org/');
?&gt;
</code></pre>

<p>Now, when you view the page containing that snippet, you will see a thumbnail generated using the Bluga WebThumb service within a few seconds that shows that web site. The thumbnail is cached locally on your server.</p>

<p>You can further customize your thumbnail with many options. You can read the full <a href="http://drupal.org/node/620684">documentation</a> for the module at Drupal&#8217;s web site as well. New features since March of last year also include a script for updating the thumbnail in place without requiring a page reload and a nicer looking (and CSS-styled) place holder, which is an improvement over the graphic previously used.</p>

<p>Last week, I was approached by the owner of <a href="http://konigi.com">Konigi.com</a> to do some Drupal work. He&#8217;s a user of the Bluga WebThumbs module I wrote in March of last year and wanted to see it work with Drupal 6. I have finished the update and have made a full release of the Drupal 5 version of the module after making a few improvements and then ported the module to Drupal 6.</p>

<p>Cheers.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Google Wave is Nothing Special</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2009/10/google-wave-is-nothing-special.html" />
    <id>tag:contentment.org,2009://3.673</id>

    <published>2009-10-15T23:28:10Z</published>
    <updated>2009-10-15T14:28:34Z</updated>

    <summary>In the past, I’ve done a fair bit of work on Jifty with Jesse Vincent by way of my previous job. He had some Google Wave invites and I begged one off of him. After waiting a week, it came...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p>In the past, I&#8217;ve done a fair bit of work on <a href="http://jifty.org">Jifty</a> with <a href="http://www.fsck.com/">Jesse Vincent</a> by way of my previous job. He had some <a href="http://wave.google.com/">Google Wave</a> invites and I begged one off of him. After waiting a week, it came through and splat. Google Wave is a wasteland of nothing. Playing with some posts to myself led to about 10 minutes of use and then I hung up.</p>

<p>A <a href="http://nowthis.com/">colleague</a> of mine, who (last I knew) does not have a Google Wave account had come across a LifeHacker <a href="http://lifehacker.com/5372853/the-first-google-wave-search-you-must-know">post</a> describe the &#8220;with:public&#8221; search that provides at least some content for Google Wave. However, that content is mostly just a dearth of &#8220;What can I do?&#8221; and &#8220;Anybody else here from Canada?&#8221; and &#8220;What happens if I post porn?&#8221; It was initially interesting, but I got about another 10 minutes and hung up again.</p>

<p>Okay, so there&#8217;s not much to do, but it&#8217;s brand spanking new. Thus, criticizing it now is like calling a bridge useless when the engineers have only just finished putting up the supports. There are couple things I&#8217;d like to note, though.</p>

<p>First, there&#8217;s not just a whole lot new here. Google Wave is merely a new combination of social networking, email, wiki, forums, chat, document and image sharing, and widgetry. If you&#8217;ve used a Wiki, Twitter, IM, and Email before, you have a good idea what Google Wave is already. They&#8217;ve just taken the next step and attempted to combine things in a way that will be challenging to scale, but I think Google is up to the task.</p>

<p>Second, that all said there is something I hope that can be achieved here, if not by Wave, by something like it. They consider Google Wave to be a reinvention of email. They have the idea that they might be able to replace email with it. Maybe. I think email has already been replaced by SMS, Twitter, and Facebook for many people. I end up using Facebook to send messages to folks much more often than Email these days and would probably use SMS if I weren&#8217;t so cheap and had someone other than my wife that I communicated with regularly via cell phone. </p>

<p>Problem: Services like Twitter and Facebook have a very significant problem. They&#8217;ve taken the Internet backwards by providing a single hosted service in the cloud. Email has an important advantage in that if my email provider has an outage, everyone else on the Internet is probably fine. If my email provider goes out of business or provides terrible service, I have the alternative to go somewhere else. Twitter and Facebook have competitors, but unless you can convince all your family and friends to move with you, you can&#8217;t leave them unless you&#8217;re willing to sever your ability to communicate with them.</p>

<p>Solution: Something like Google Wave or Twitter or a consortium of social networking sites needs to come up with a new decentralized mechanism for communicating between people. Whether that means you can switch services but they have hooks between one another to send messages and share friend lists or Google Wave provides some sort of decentralized platform for doing this independent of the social networking sites, something needs to happen here.</p>

<p>There are other dangers here to privacy and such that I haven&#8217;t even touched on either. Something like Google Wave (assuming Google Wave can become decentralized like email) should happen if social networking is going to continue to develop. That&#8217;s my thought anyway.</p>

<p>Cheers.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Driving an Empty Bus or a Clown Car?</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2009/09/driving-an-empty-bus-or-a-clow.html" />
    <id>tag:contentment.org,2009://3.670</id>

    <published>2009-09-11T02:44:30Z</published>
    <updated>2009-09-11T03:00:34Z</updated>

    <summary>This morning I had an epiphany about a difference in project management style between the two major development jobs I’ve held. One style was like driving an empty bus and the other was like riding in a clown car. I...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
    <category term="development" label="development" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="fun" label="fun" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="management" label="management" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="project" label="project" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="software" label="software" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="style" label="style" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="work" label="work" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p>This morning I had an epiphany about a difference in project management style between the two major development jobs I&#8217;ve held. One style was like driving an empty bus and the other was like riding in a clown car. I am going to examine both as anecdotes from my perspective and try to avoid grandiose analysis.</p>

<h3>The Empty Bus</h3>

<p>So, I start the job and the first thing the company does is hand me the keys to the bus. Actually, they dither on what kind of bus to give me for several months before getting me a suitable one and give me a loaner to drive in the meantime. However, once on the bus driving, I am pretty much on my own. I have a destination to reach that has been vaguely described on a scribbled piece of paper. The directions are unclear and no one in the company has been there before. They keep changing the directions. But I get to drive. That is fun.</p>

<p>Every now and then, I pick somebody from the company up, they make changes to the directions and then they get off again before I go very far. Every six months, everybody climbs on to the bus and sits in the very back. They do a lot of yelling while I park and then they take away my scribbled directions and give me new scribbles to follow and a new destination to reach. But I get to drive. That&#8217;s usually fun.</p>

<p>All in all, I am asked to develop software with very little cooperation or direction. I am left on my own to make almost all the decisions. Even though I have weekly meetings with my manager, I am not really given much feedback on whether I&#8217;m going the right way. He&#8217;s not a developer, so he doesn&#8217;t really know enough about what I do to give me useful feedback. My quarterly reviews aren&#8217;t very cooperative or helpful, they are more about the manager wishing I would drive faster and make fewer mistakes (mutually exclusive goals when you think about it).</p>

<p>I nearly get into a wreck a couple times, but there&#8217;s no one on the bus to help me out. Don&#8217;t get me wrong, I&#8217;m not an excellent driver. I&#8217;m still learning, but some help should help things go faster in process, you&#8217;d think. Usually, though, my directions are so unclear and difficult to follow that I am directed to get into wrecks. This is not actually all that fun as time goes on.</p>

<h3>The Clown Car</h3>

<p>Clown cars are funny. They drive around in circles and then the doors pop open and an absurd number of hilarious characters hop out of the little car. This job is not quite like this. It&#8217;s actually more like a really crowded minivan, like the trip I took the other day with my wife, son, dad, mom, brother, sister, and her boyfriend, all crammed into our little Pontiac Montana. But now, imagine, that all of these people have a stake in where the van goes and have a slightly role and different idea about how to go about getting there. Now, we&#8217;ve got a good analogy. Clown cars are fun, though.</p>

<p>The CEO&#8217;s seat is next to mine and he gets in and out of the van whenever he feels the need. He&#8217;s a busy man: lots of vans to help. Usually, he gets in right before we wreck or near the major turns to make sure we drive carefully at those point and turn the right direction. Directly behind me sits an analyst whose job it is to navigate. He tells me where to go and annotates those instructions pretty regularly. Beside him sits another analyst whose job it is to talk to the customer and figure out what they want. He then tells the first analyst and me where we need to think about going next. I get to drive, though, they keep reaching from the back for the wheel and the pedals. That&#8217;s annoying, but still fun.</p>

<p>Behind the analysts sit a whole team of project managers, executives, sales people and between them and between the front seats sit a bunch of other engineers. Sometimes the other engineers help drive, make suggestions, and they often critique or commend my driving. There are a lot of people in this minivan, sometimes there&#8217;s a lot of yelling about what to do next. All the activity does make for quite a bit of fun, even if it gets a bit distracting at times.</p>

<p>I get to drive. As I mentioned, sometimes the analysts and engineers have their hand on the wheel and help push the pedals for me. This is pretty fun too, unlike the car though, this actually gives us a lot more control. We seem to be getting places in a much more controlled way, though we do have to control our speed much more carefully. It might take us longer, but the drive is fun along the way.</p>

<p>Software development in this style takes away some of my freedom as a coder. That&#8217;s a bummer in some ways, not as much fun. I like control. Yet, it also lets me focus on my strengths while others worry about talking to customers, making sure we have a plan that does what the customer wants, and while the constant feedback makes it hard to see the big picture, I usually have a lot of warning before I drive off the road or get into a wreck. Overall, this is more fun.</p>

<p>So far, I prefer the &#8220;clown car&#8221;/stuffed minivan to the empty bus. It&#8217;s less bipolar and more slow, steady, and directed.</p>

<p>Cheers.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Mario AI Competition and Perl</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2009/08/mario-ai-competition-and-perl.html" />
    <id>tag:contentment.org,2009://3.667</id>

    <published>2009-08-17T14:15:30Z</published>
    <updated>2009-08-17T14:45:24Z</updated>

    <summary>Last week, a coworker let me know about this. It’s been on Slashdot and such, but I’m a little behind on my feeds. For some reason, the competition intrigued me so I’ve put together a set of Perl classes that...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p>Last week, a coworker let me know about this. It&#8217;s been on Slashdot and such, but I&#8217;m a little behind on my feeds. For some reason, the competition intrigued me so I&#8217;ve put together a set of Perl classes that will allow agents written in Perl to control the Mario AI simulator using the server agent. I considered trying Java, but I started and quickly remembered why I hate Java, so I quit that and wrote this up over the weekend instead. You can fork it and give it a look here.</p>

<ul>
<li><a href="http://github.com/zostay/AI-Mario/tree/master">http://github.com/zostay/AI-Mario/tree/master</a></li>
</ul>

<p>It includes a very stupid and blind robot for testing at this point. However, it is able to get through most levels I&#8217;ve tried on difficulty 0 (though, not many on any higher difficulty). Once you install that and fetch the latest JAR file from the Mario AI competition site:</p>

<ul>
<li><a href="http://github.com/zostay/AI-Mario/tree/master">http://groups.google.com/group/mariocompetition/files</a></li>
</ul>

<p>You can then run an agent via:</p>

<pre><code>java -jar iMario.jar -server on
</code></pre>

<p>to start the server, then:</p>

<pre><code>cd AI-Mario
bin/agent.pl
</code></pre>

<p>This will run the blind Perl agent (named <code>AI::Mario::Agent::Simple</code>) on the same level over and over. A more interesting run might be:</p>

<pre><code>bin/agent.pl --config AI::Mario::Config::Random -o level_difficulty=2
</code></pre>

<p>This will run the same agent through a random series of levels (restarting each time the agent wins or loses) and sets the level difficulty to 2&#8212;which means, the simple agent nearly always loses.</p>

<p>The system is built with Modern Perl (i.e. Moose) and uses POE and POE::Declarative to talk to the Mario AI server agent. You can implement new configuration (to customize how options are set at the start of each run) and agent and set them to run using the arguments available on the CLI.</p>

<p>To write an agent, for example, you just need to create a class that does the <code>AI::Mario::Agent</code> role and implements the required methods.</p>

<ul>
<li><strong>name</strong>: should return the agent name to be sent to the server agent as greetings</li>
<li><strong>reset</strong>: a method called to reset the agent when a simulation is about to start</li>
<li><strong>update</strong>: a method called during each frame, given an observation object (see <code>AI::Mario::Observation</code>) and should set the <code>left</code>, <code>right</code>, <code>duck</code>, <code>jump</code>, and <code>run</code> controls appropriately to keep moving.</li>
<li><strong>fitness</strong>: this is called at the end of the simulation with a fitness report to tell the agent how well it did (see <code>AI::Mario::Fitness</code>)</li>
</ul>

<p>Then, you can run your agent via:</p>

<pre><code>bin/agent.pl --agent MyAgentClass -p foo=1
</code></pre>

<p>where you can pass a series of parameters to the agent constructor using the <code>-p</code> option.</p>

<p>I plan to add a bit more to it, but the interface is mostly set.</p>

<p>I&#8217;m not even sure they&#8217;ll accept a Perl submission, but it seems to be implied by the instructions on the site. I&#8217;ve asked to be sure. If I can confirm that, I&#8217;ll also add a <code>Makefile.PL</code> and such so that the solution can be packaged with all the required libraries to make it run.</p>

<p>I still haven&#8217;t decided whether or not to enter or just goof around, but whatever. :)</p>

<p>Cheers.</p>

<p><strong>Update:</strong> Julian already replied. Yes, Perl submissions would be accepted. I&#8217;ll definitely try to add a submission script which will help build all the requirements to submit.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Goofing Around with HTML 5 Canvas</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2009/08/goofing-around-with-html-5-can.html" />
    <id>tag:contentment.org,2009://3.666</id>

    <published>2009-08-08T04:53:04Z</published>
    <updated>2009-08-08T05:05:53Z</updated>

    <summary>I was goofing around with HTML 5 canvas for giggles this week. The canvas allows you to draw using JavaScript to a section of the page. HTML 5 defines a “2d” context, which allows you to draw lines, polygons, images,...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p>I was goofing around with HTML 5 canvas for giggles this week. The canvas allows you to draw using JavaScript to a section of the page. HTML 5 defines a &#8220;2d&#8221; context, which allows you to draw lines, polygons, images, boxes, etc. You can style your stroke, fill, and shadow, etc. It&#8217;s pretty easy to goof around with. Oh, and if you&#8217;re using Internet Explorer, these won&#8217;t work. You&#8217;re out of luck because Microsoft is too cool for canvas.</p>

<h3>Box Fractal Renderer</h3>

<p>First, I built a box fractal renderer, which are my favorite things to doodle on graph paper.</p>

<p><canvas id="vicsek" style="width:100%;height:200px;background:white"></canvas></p>

<script language="JavaScript">
;(function(){
var canvas = document.getElementById('vicsek');
canvas.width  *= 5;
canvas.height *= 5;
var size = Math.min(canvas.width, canvas.height);
var c = canvas.getContext('2d');

function draw_square(x, y, size) {
    c.fillRect(x, y, size, size);
}

function draw_squares(x, y, size, iter) {
    var draw_next = iter > 0 ? draw_squares : draw_square;
    var next_size = size / 3;
    var next_iter = iter - 1;

    draw_next(x, y, next_size, next_iter);
    draw_next(x + next_size * 2, y, next_size, next_iter);
    draw_next(x, y + next_size * 2, next_size, next_iter);
    draw_next(x + next_size, y + next_size, next_size, next_iter);
    draw_next(x + next_size * 2, y + next_size * 2, next_size, next_iter);
}
draw_squares(0, 0, size, 5);
})();
</script>

<h3>Fractal Coastline</h3>

<p>Then, I played some more with fractals and eventually ended up with this fractal coastline builder. Each view of this will be a little different. Some look more like coastlines than others.</p>

<p><canvas id="coastline" style="width:100%;height:200px;background:white"></canvas></p>

<script language="JavaScript">
;(function(){
var canvas = document.getElementById('coastline');
canvas.width  *= 5;
canvas.height *= 5;
var c = canvas.getContext('2d');

function LinePoint(pos, delta) {
    this.pos   = pos;
    this.delta = delta - 0.5;
}

function Point(x, y) {
    this.x = x;
    this.y = y;
}

var length = Math.random() * 8 + 4;
var line_points = new Array();
for (var i = 0; i < length; i++) {
    line_points.push(new LinePoint(Math.random(), Math.random()));
}
line_points = line_points.sort(function(a, b) { return a.pos - b.pos; });

var start = new Point(0, Math.random() * canvas.height);
var end   = new Point(canvas.width, canvas.height - start.y);

function draw_segments(start, end, iter, coeff) {
    var draw_next = iter > 0 ? draw_segments : draw_segment;
    var last = start;

    var delta = new Point(end.x - start.x, end.y - start.y);
    var det   = Math.sqrt(delta.x * delta.x + delta.y * delta.y);
    var perp  = new Point(-delta.y / det, delta.x / det);

    // console.log("DELTA");
    // console.dir(delta);
    // console.log("PERP");
    // console.dir(perp);
    // console.log("COEFF = " + coeff);

    //console.log("x = " + start.x + ", y = " + start.y);
    for (var i = 0; i < line_points.length; i++) {
        var line_point = line_points[i];

        var x = start.x + delta.x * line_point.pos 
                        + perp.x  * line_point.delta * coeff;
        var y = start.y + delta.y * line_point.pos
                        + perp.y  * line_point.delta * coeff;
        var next = new Point(x, y);
        // console.log("NEXT");
        // console.dir(next);

        //console.log("x = " + x + ", y = " + y + ", line_point.delta = " + line_point.delta);
        draw_next(last, next, iter - 1, coeff / 4);
        last = next;
    }
    //console.log("x = " + end.x + ", y = " + end.y);
    draw_next(last, end, iter - 1, coeff / 4);
}

function draw_segment(start, end) {
    c.lineTo(end.x, end.y);
}

c.strokeStyle = 'black';
c.fillStyle = 'silver';

c.beginPath();
c.moveTo(start.x, start.y);
draw_segments(start, end, 3, 300);
c.lineTo(canvas.width, canvas.height);
c.lineTo(0, canvas.height);
c.lineTo(start.x, start.y);
c.stroke();
c.fill();
})();
</script>

<p>Anyway, just some random goofing off I thought I&#8217;d share.</p>

<p>Cheers.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Time Estimation Sucks</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2009/07/time-estimation-sucks.html" />
    <id>tag:contentment.org,2009://3.664</id>

    <published>2009-07-29T01:43:22Z</published>
    <updated>2009-07-28T21:19:13Z</updated>

    <summary>From the perspective of myself, a software developer, time estimation always sucks. I believe I’m working in an environment which has a better view of time estimation than those I’ve worked in before, but we still do it and I...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p>From the perspective of myself, a software developer, time estimation always sucks. I believe I&#8217;m working in an environment which has a better view of time estimation than those I&#8217;ve worked in before, but we still do it and I think that it&#8217;s sucking is inherent. I&#8217;ll explain why in a minute.</p>

<p>However, I want to say that time estimation is probably essential for project managers, product managers, executives, sales, and the like. For them, perhaps they can provide a barometer giving them a good indication of where things will be in the future. However, I don&#8217;t speak for any of them, I&#8217;m speaking from the selfish position in which I stand (as we all do and would admit when we&#8217;re being honest).</p>

<h3>Time Estimates are Guesses</h3>

<p>A time estimate is, by definition, going to be inaccurate. Until someone finds a prophet willing to use his gift for mundane predictions like, &#8220;How long will this new feature take to implement?&#8221; Or, &#8220;What&#8217;s the timeline on this fix?&#8221; The answer will be wrong. </p>

<p>To a person without the training it may seem like a software developer works magic and comes up with solutions, but that&#8217;s not the case. She&#8217;s merely working through developing an explicit set of directions, logic, and math to allow the computer to do something. However, the complexity of a problem is rarely well-known until you try to work through it. Thus, you don&#8217;t know what problems you are going to run into.</p>

<p>This is further complicated by the fact that you have to work within some framework including programming language, available libraries, code already in built up, customer expectations, code maintainability, solution flexibility, etc. A software developer often has to make decisions and compromises along the way and it&#8217;s not always clear what the ramifications of each of these decisions will have.</p>

<h3>Implied Margin of Error</h3>

<p>All time estimates include an implied, but rarely recorded or even knowable, margin of error. When I estimate the time it will take to do something, I will often say something like, &#8220;Well, since I just did a very similar process in importing that fail for client X, it will take about 2/3rd&#8217;s as much time to do it for client Y since I&#8217;m familiar with the code and added some pieces there to make doing this task easier.&#8221; I&#8217;m implying a narrow margin of error.</p>

<p>On the other hand, I might say, &#8220;Well, the code in that part of the application was not well future-proofed and this will build on there. I may have to do some refactorings, so I&#8217;d say we&#8217;re looking at 2 days, plus or minus a week.&#8221; I&#8217;m even stating it here, the large margin error.</p>

<p>Yet, what if the first task turns out to take 5 times as long as I said, does that mean my margin of error was wrong or does that mean I was operating on incomplete information? </p>

<p>When a meteorologist says, &#8220;50%&#8221; chance of rain, is he wrong when it rains on your house? Or when it doesn&#8217;t? No, it was just an estimate, which is a statistical entity that cannot be analyzed on those terms as a data point. Only after you have a collection of data points that shows that when the meteorologist suggested 50% chance of rain, it actually rained 60% of the time. Then, he&#8217;s been wrong (and even in this analysis, you have to be careful about data bias and all the other statistical issues your analysis may contain).</p>

<h3>Large Estimates</h3>

<p>Getting into the actual business case, we find that making a large time estimate on something will get you into trouble when you make the estimate. </p>

<p>I recall a case when I suggested I was starting on something during the last week of December after Christmas. I broke the task down into all the steps I would have to do to complete the task and concluded that an reasonable estimate of time would be the end of the second week of February. I told this to the executive in charge of the product and he said, &#8220;We&#8217;d really like to be able to tell the clients the start of the third week in January.&#8221; I said, &#8220;No. I don&#8217;t think that&#8217;s reasonable.&#8221; He said, &#8220;We&#8217;d really like to be able to tell the clients the start of the third week in January.&#8221; In other words, &#8220;I don&#8217;t care what your estimate is, this is the estimate we&#8217;ll use.&#8221; My response, &#8220;I will give you something at that time, but it won&#8217;t be finished.&#8221; </p>

<p>In this case, it actually took all the way through April to get it done, largely because the project ended up having twice as many features as originally spec&#8217;d.</p>

<p>As a software developer, I am strongly motivated to report short estimates to avoid pressure from above. Sometimes, however, a long estimate is the only one that will work, but I always expect to be criticized if I give a long estimate on something.</p>

<h3>Short Estimates</h3>

<p>If I end up giving an estimate for a project that actually takes me 2 to 5 times as long to complete, then I&#8217;m in big trouble. These are the times when executives yell at people. Directors and project leads ask you what lessons you&#8217;ve learned, and if someone really gets upset, you have weekly phone calls with someone in HR listening in.</p>

<p>So here&#8217;s where making a long estimate for a short task seems like a good idea. But then, what happened in the last section? There&#8217;s no win in this game.</p>

<h3>Accurate Estimates</h3>

<p>So what happens when you get it dead on? Do you get a big promotion, cigars and cognac with the executives, and a fat bonus? Nope. You just plod on. You might get such if you made a long estimate, got away with it, and then delivered way early, but that might just mean you&#8217;re a good con-artist, not necessarily good at estimating your time.</p>

<h3>What&#8217;s the Answer?</h3>

<p>I don&#8217;t have one for managers. That&#8217;s not my problem, but managing my managers is. So, here&#8217;s the solution (at least what seems to work best for me at this point):</p>

<ol>
<li><p><strong>Communicate frequently with the bosses.</strong> Anyone you know to be a stakeholder in your project should get something from you often enough to keep them in the loop, but not so often they get annoyed. Hard to balance, but in generally you ought to be talking to your supervisor at least once every day, your project/product managers should get information at least twice a week and as much as once every day, and executives should get direct feedback from you once a week if they have a stake.</p>

<p>And if you find out something is really critical to someone, update them as often as your supervisor. If it&#8217;s an emergency or something critical to a sales pitch being made tomorrow, send out an update at every stopping point. </p>

<p>Regular status reports help managers feel in control and you want them to feel in control. If they feel out of control, expect them to blame you for not telling them what was going on.</p></li>
<li><p><strong>Make your guesses as good as you can.</strong> On complex tasks, break the task down as far as you can ahead of time and estimate each piece. Give yourself an explicit margin of error and percentage of accuracy you&#8217;d place on that margin. Sum up the time estimates and margins and use that to present you estimate. Take some time to do this well, don&#8217;t rush and spend more time considering the harder to estimate parts.</p>

<p>When you give your estimate, you might share some or all of this with your supervisor (depending on how well you think he&#8217;ll be able to cope with the information). Don&#8217;t give this to anyone else, but use this information to determine how to talk about it when reporting on your estimate. Use vague, fuzzy language for parts you aren&#8217;t sure about and use concise, direct language on the parts you are pretty sure about.</p></li>
<li><p><strong>Stand by your estimate.</strong> If your boss says, &#8220;Unacceptable,&#8221; or doubts you, listen to them and explain more about your estimate. Especially if you&#8217;ve worked through the time it will take in details, wavering in a moment of doubt is probably not going to serve you or anyone.</p></li>
<li><p><strong>Be flexible.</strong> If the bosses need a shorter estimate for some reason or even expected a longer one, use that to your advantage. If you&#8217;ve done your homework and got it with you, perhaps you can negotiate parts of the spec away that aren&#8217;t as critical in order to cut down on time. Or perhaps there are things you can iron out a little better and get working really well in the time you have. Or perhaps you can use that opportunity at the tail end to get better testing and quality in place.</p></li>
<li><p><strong>Meekness wins when all else fails.</strong> Never ever burn your bridges. When it hits the fan because you prove to be the woeful prophet you are, stand by your mistake, but stay calm. Be humble. You might have a really good idea what went wrong, but your bosses are pointing at something else. Point that out, but don&#8217;t beat them with it if they disagree.</p></li>
</ol>

<p>Other than that, be you. I work really hard to never blame someone for a mistake, even if they made it. I do not tell on fellow employees when they aren&#8217;t doing their job. However, I try to make it a point to point out excellence in my fellows whenever I can. I don&#8217;t feel like it&#8217;s my job to do management (which, in my mind, means correcting and rebuking employees when they fail at something), but pointing out excellence and success is everyone&#8217;s business. If I really appreciate something a fellow developer has done or someone on the business side writing a really great spec, I try to make it a point to say so in conversation. Unfortunately, being the loner that I am, I don&#8217;t think I notice these things as often as I could.</p>

<p>Time estimation sucks, but it&#8217;s pretty much inevitable. The key is understanding why it sucks and how to deal with that.</p>

<p>Cheers.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Weight Loss, My Way</title>
    <link rel="alternate" type="text/html" href="http://contentment.org/2009/06/weight-loss-my-way.html" />
    <id>tag:contentment.org,2009://3.662</id>

    <published>2009-06-25T17:24:04Z</published>
    <updated>2009-06-25T18:59:53Z</updated>

    <summary>Disclaimer: IANAD: I AM NOT A DOCTOR. Please consult one prior to engaging in any attempt at weight loss. I provide no recommendation you do things my way and take no responsibility for your health. Disclaimer 2: I am not...</summary>
    <author>
        <name>Andrew Sterling Hanenkamp</name>
        <uri>http://andrew.sterling.hanenkamp.com</uri>
    </author>
    
    
    <content type="html" xml:lang="en-us" xml:base="http://contentment.org/">
        <![CDATA[<p><strong>Disclaimer:</strong> <em>IANAD: I AM NOT A DOCTOR. Please consult one prior to engaging in any attempt at weight loss. I provide no recommendation you do things my way and take no responsibility for your health.</em></p>

<p><strong>Disclaimer 2:</strong> <em>I am not affiliated with, have never given money to, and have no relationship at all with the <strong>Unnamed Diet System</strong> I have based my diet plan upon. I do not recommend for or against their system, I am just sharing the fact that I my own variation of it and have had success.</em></p>

<p>Since my birthday this year, I&#8217;ve been working to lose a little extra weight. I now weigh around what I did when I was in high school and am still losing. I did this to show solidarity with my wife who wanted to lose a bit, but I needed to do this for myself as well.</p>

<p>Wanting to lose weight presented a few problems for me. First, I can not stand to do what somebody else tells me to do. My wife calls that being &#8220;obstinate-defiant.&#8221; Depending on my mood I usually either say I&#8217;m just selfish or I have a built-in distrust of the crowd. In any case, it was clear that unless I could tweak my plan a bit, I wasn&#8217;t going to be be happy with it. I&#8217;ve ended up tweaking less than I thought I would, but I still can, so there.</p>

<p>My next problem is that I refuse to do cruel or unusual dieting. I&#8217;m not going in for any fad or diet that drastically changes things. I&#8217;m not giving up cookies or eating grapefruit or doing Adkins. Regardless of what science there is or is not backing these things up, anything that changes what I eat is going to make me grumpy. I <em>love</em> food and there is no shame in that. The shame comes in consistently eating more than I need. I also find the idea of using a pill or surgery repulsive (no offense to those who do such, I won&#8217;t). For me, this process is about developing self-control, which means I need to learn to do it and my wife provides enough accountability to that end.</p>

<p>While metabolism and other factors adjust a person&#8217;s dietary needs, failure to consume enough calories to maintain a person&#8217;s current weight will cause a reduction. (Unless, which I suppose is possible, a person&#8217;s body is somehow capable of storing fat, but incapable of using it. I don&#8217;t know if any such disease exists, but I don&#8217;t have it if it does, so it&#8217;s not my problem.) Therefore, my diet plan would have to be something as mundane as journaling what I eat.</p>

<p>Which brings up my next problem, counting calories is too easy and not really addressing the full magnitude of the problem. Because not only should I eat less, but I should encourage myself to eat healthier. The system ought to take other factors into account.</p>

<p>My final problem is that whatever it is I do must be something I can do on a computer. I sit in front of one for around 8-12 hours per day. I can set my computer to remind of things, I can share things between myself and my wife to provide accountability on my computer, and while I like writing down notes, particularly when I&#8217;m brainstorming, I really don&#8217;t want to do all the math we&#8217;re talking about in my head all the time. It&#8217;s too tedious.</p>

<p>Fortunately, my wife <a href="http://terri.hanenkamp.com/ww/">previously</a> went on and successfully completed a plan using <strong>Unnamed Diet System</strong> for which you may have seen ads. This system met all my basic requirements. Yet, other than they way they count points, they don&#8217;t provide any value to me, at least none I would pay for. Fortunately, everything I needed was published at various places on the Internet and I built myself a Google Docs spreadsheet to do it.</p>

<p>I provide a link to a version of it here for anyone interested in weight loss on similar terms. <em>Go re-read the disclaimers again now.</em> I&#8217;ll wait&#8230; Done? Okay, I don&#8217;t recommend this plan to you, but if you find the spreadsheet useful, great. I&#8217;m providing it under a <a href="http://creativecommons.org/licenses/by/3.0/us/">Creative Commons 3.0</a> license. </p>

<ul>
<li><a href="http://spreadsheets.google.com/ccc?key=rEBiFNc8PjWLNtjKepbm00g">Food Points Sheet</a></li>
</ul>

<p>If you have a Google account, you can create a copy of the spreadsheet to use it or you can download it in another format to use with Excel or OpenOffice (I think, haven&#8217;t tried that).</p>

<p>To use it, I first scroll right until I fill in some information about myself. This sets up the basic tolerances for my diet plan based upon sex, age, current weight, height, daily activity, etc. Then scroll back left and log my consumption. Under each meal, the wide column is for a description of the item eaten and the narrow for recording the points. Once I have &#8220;0&#8221; points left for the day, I stop eating. The spreadsheet does have a weekly allowance of extra points that I can use as well to indulge in something or just allow me to consume all the points for a day without worrying about going over by a couple. I use all the points I have for a day unless I&#8217;m really not hungry. This is not a starvation diet, so I try to use up as many of my daily points as possible. I do not worry too much about using or not using the weekly points. I often consume most of them.</p>

<p>The formula for calculating this points is simple, but elegant in that it encourages me to get more fiber and avoid fatty foods, while consuming fewer calories than I need to maintain my weight:</p>

<pre><code>Points = Calories / 50 + Fat (g) / 12 + MIN(Fiber (g) / 5, 1)
</code></pre>

<p>I&#8217;ve been told that <strong>Unnamed Diet System</strong> actually divides Fiber by 4, but whatever. I have embedded a couple calculators in the spreadsheet for the times when I&#8217;m too lazy to do the math in my head.</p>

<p>I weigh myself once a week to track my progress (on a separate spreadsheet).Every 10 pounds, I adjust the chart to the right since the spreadsheet gives one less point per day for each 10 pounds I lose. I also copy the spreadsheet (actually, Terri manages this part) each week and blank it out to use the next week.</p>

<p>Eventually, I should reach my goal weight (I haven&#8217;t really decided what that is). When that happens, I&#8217;ll need to adjust the spreadsheet to deal with maintenance. When that happens, I will give myself more points until my weight stabilizes. I plan to continue recording points for the foreseeable future this way.</p>

<p>Cheers.</p>
]]>
        

    </content>
</entry>

</feed>

