<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Mike Friedman</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/" />
    <link rel="self" type="application/atom+xml" href="http://blogs.perl.org/users/mike_friedman/atom.xml" />
    <id>tag:blogs.perl.org,2009-11-03:/users/mike_friedman//100</id>
    <updated>2012-10-16T21:01:10Z</updated>
    <subtitle>Musings about Perl, programming, and the art of good software</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.38</generator>

<entry>
    <title>Building Your First App with MongoDB and Perl at MongoDB Boston</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2012/10/building-your-first-app-with-mongodb-and-perl-at-mongodb-boston.html" />
    <id>tag:blogs.perl.org,2012:/users/mike_friedman//100.3963</id>

    <published>2012-10-16T20:59:15Z</published>
    <updated>2012-10-16T21:01:10Z</updated>

    <summary>I&apos;ll be speaking on October 24th at MongoDB Boston 2012, taking place at the lovely Marriot Courtyard Tremont/Downtown. Conference registration is a mere $100 ($30 for students). There are three tracks, covering everything from beginner topics presented by 10gen staff to advanced, detailed MongoDB presentations by industry leaders. Here&apos;s the abstract for my talk: This talk introduces the features of MongoDB by demonstrating how one can build a simple library application. The talk will cover the basics of MongoDB&apos;s document model, query language, and API. In addition, we will learn how to use MongoDB within a typical web application framework. If you&apos;re in Boston and you&apos;ve never used MongoDB before, or are thinking of trying it out, I&apos;d highly recommend stopping by. The demo application for the talk is written with Mojolicious::Lite and will soon be available on GitHub for you to experiment with. (Crossposted from my blog here.)...</summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    <category term="perlmongodbboston" label="perl mongodb boston" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[<p>I'll be speaking on October 24th at <a href="http://www.10gen.com/events/mongodb-boston">MongoDB Boston 2012</a>, taking place at the lovely <a href="http://www.marriott.com/hotels/travel/bosdm-courtyard-boston-downtown-tremont/">Marriot Courtyard Tremont/Downtown</a>. </p>
<p>Conference registration is a mere $100 ($30 for students). There are three tracks, covering everything from beginner topics presented by 10gen staff to advanced, detailed MongoDB presentations by industry leaders. Here's the abstract for my talk:
<blockquote>
This talk introduces the features of MongoDB by demonstrating how one can build a simple library application. The talk will cover the basics of MongoDB's document model, query language, and API. In addition, we will learn how to use MongoDB within a typical web application framework.
</blockquote>
</p>
<p>
If you're in Boston and you've never used MongoDB before, or are thinking of trying it out, I'd highly recommend stopping by. The demo application for the talk is written with <a href="https://metacpan.org/module/Mojolicious::Lite">Mojolicious::Lite</a> and will soon be available on GitHub for you to experiment with.
</p>
<p>
(Crossposted from my blog <a href="http://friedo.com/blog/2012/10/building-your-first-app-with-mongodb-and-perl-at-mongodb-boston">here</a>.)</p>]]>
        
    </content>
</entry>

<entry>
    <title>MongoDB drops support for Perl 5.8.</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2012/10/mongodb-drops-support-for-perl-58.html" />
    <id>tag:blogs.perl.org,2012:/users/mike_friedman//100.3944</id>

    <published>2012-10-10T22:17:43Z</published>
    <updated>2012-10-10T22:21:13Z</updated>

    <summary>One of my many rules of software engineering, born of more than a decade seeing things done the Wrong Way, is that serialization must occur only at the extreme edges of your program. At all other points you should, if possible, deal only with structured data. The lack of it in one crucial area of the Perl MongoDB driver is what made support for Perl 5.8 no longer possible. Read more about my rationale for this change at my blog here: Structured Data and the Road to Obsolescence....</summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[<p>One of my many rules of software engineering, born of more than a decade seeing things done the Wrong Way, is that serialization must occur only at the extreme edges of your program. At all other points you should, if possible, deal only with structured data. The lack of it in one crucial area of the Perl MongoDB driver is what made support for Perl 5.8 no longer possible.</p>

<p>Read more about my rationale for this change at my blog here: <a href="http://friedo.com/blog/2012/10/structured-data-and-the-road-to-obsolescence">Structured Data and the Road to Obsolescence</a>.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Fast datetimes in MongoDB</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2012/09/fast-datetimes-in-mongodb.html" />
    <id>tag:blogs.perl.org,2012:/users/mike_friedman//100.3839</id>

    <published>2012-09-17T02:33:56Z</published>
    <updated>2012-09-17T02:36:16Z</updated>

    <summary>One of the most common complaints about the Perl MongoDB driver is that it tries to be a little too clever. In the current production release of MongoDB.pm (version 0.46.2 as of this writing), all datetime values retrieved by a query are automatically instantiated as DateTime objects. The next release of MongoDB.pm will fix this problem, allowing for nearly tenfold speed increases under some circumstances. The details are available on my blog here: Fast datetimes In MongoDB....</summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    <category term="datetime" label="datetime" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="mongodb" label="mongodb" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[<p>One of the most common complaints about the Perl MongoDB driver is that it tries to be a little too clever. In the current production release of MongoDB.pm (version 0.46.2 as of this writing), all datetime values retrieved by a query are automatically instantiated as DateTime objects. </p>
<p>
The next release of MongoDB.pm will fix this problem, allowing for nearly tenfold speed increases under some circumstances. The details are available on my blog here: <a href="http://friedo.com/blog/2012/09/fast-datetimes-in-mongodb">Fast datetimes In MongoDB</a>.]]>
        
    </content>
</entry>

<entry>
    <title>MongoDB 0.46.1 Released</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2012/09/mongodb-0461-released.html" />
    <id>tag:blogs.perl.org,2012:/users/mike_friedman//100.3788</id>

    <published>2012-09-05T14:51:27Z</published>
    <updated>2012-09-05T14:53:57Z</updated>

    <summary>I&apos;m happy to announce that version 0.46.1 of the Perl MongoDB driver has been released to CPAN! It should make its way to your local mirror soon. This release has mostly minor bugfixes and some housekeeping, but more and better stuff is coming down the line. I&apos;ve written a detailed post about the release and future plans on my blog here: MongoDB 0.46.1 Released. Enjoy!...</summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    <category term="mongodb" label="mongodb" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[I'm happy to announce that version 0.46.1 of the Perl MongoDB driver has been released to CPAN! It should make its way to your local mirror soon. This release has mostly minor bugfixes and some housekeeping, but more and better stuff is coming down the line. I've written a detailed post about the release and future plans on my blog here: <a href="http://friedo.com/blog/2012/09/mongodb-0461-released">MongoDB 0.46.1 Released</a>. Enjoy!]]>
        
    </content>
</entry>

<entry>
    <title>Two new Pod::Weaver plugins</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2011/12/two-new-podweaver-plugins.html" />
    <id>tag:blogs.perl.org,2011:/users/mike_friedman//100.2537</id>

    <published>2011-12-04T21:47:29Z</published>
    <updated>2011-12-05T00:30:05Z</updated>

    <summary>After falling in love with Pod::Weaver, I&apos;ve released two new Pod::Weaver plugins which you may find useful for assembling boilerplate POD sections in your distributions. The first is Pod::Weaver::Section::Extends which will add a =head1 EXTENDS section with a list of everything in your @ISA at compile-time. It should work with any kind of object that modifies @ISA in a normal way. The second is Pod::Weaver::Section::Consumes, which does the same thing for Moose roles. It will interrogate any Moose-compatible meta object for your class to find a list of roles. The repositories for them are here and here....</summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    <category term="perlmooseooppodweaverdistzillacpan" label="perl moose oop pod-weaver dist-zilla cpan" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[<p>After <a href="http://blogs.perl.org/users/mike_friedman/2011/11/falling-in-love-with-podweaver.html">falling in love with Pod::Weaver</a>, I've released two new Pod::Weaver plugins which you may find useful for assembling boilerplate POD sections in your distributions.
</p>
<p>
The first is <a href="https://metacpan.org/module/Pod::Weaver::Section::Extends">Pod::Weaver::Section::Extends</a> which will add a <code>=head1 EXTENDS</code> section with a list of everything in your <code>@ISA</code> at compile-time. It should work with any kind of object that modifies <code>@ISA</code> in a normal way.
</p>
<p>
The second is <a href="https://metacpan.org/module/Pod::Weaver::Section::Consumes">Pod::Weaver::Section::Consumes</a>, which does the same thing for Moose roles. It will interrogate any Moose-compatible <code>meta</code> object for your class to find a list of roles.
</p>
<p>
The repositories for them are <a href="https://github.com/friedo/pod-weaver-section-extends">here</a> and <a href="https://github.com/friedo/pod-weaver-section-consumes">here</a>. 
</p>
]]>
        <![CDATA[<p>
Enjoy!
</p>]]>
    </content>
</entry>

<entry>
    <title>Falling in love with Pod::Weaver</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2011/11/falling-in-love-with-podweaver.html" />
    <id>tag:blogs.perl.org,2011:/users/mike_friedman//100.2500</id>

    <published>2011-11-28T03:53:48Z</published>
    <updated>2011-11-28T05:35:10Z</updated>

    <summary>I&apos;ve been working on Redis::Client for a while now. It&apos;s not ready for production use yet, and there&apos;s a lot of work yet to be done, but it&apos;s much better than anything else on CPAN right now for talking to Redis. I hate boilerplate with a burning passion, and I will often go to extreme lengths to avoid typing it. (I typed it once already, dammit! Leave me alone!) After having a great time learning to mess with Dist::Zilla, I decided to give another of Ricardo&apos;s projects, Pod::Weaver a try. Here&apos;s the cool stuff I was able to do after not a lot of work....</summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    <category term="podpodweaverdistzillaredisperlmoose" label="pod pod-weaver dist-zilla redis perl moose" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[<p>I've been working on <a href="https://github.com/friedo/perl-redis-client">Redis::Client</a> for a while now. It's not ready for production use yet, and there's a lot of work yet to be done, but it's much better than anything else on CPAN right now for talking to <a href="http://redis.io/">Redis</a>.</p>

<p>I hate boilerplate with a burning passion, and I will often go to extreme lengths to avoid typing it. (I typed it once already, dammit! Leave me alone!)</p>

<p>After having a great time learning to mess with Dist::Zilla, I decided to give another of <a href="http://rjbs.manxome.org/rubric/entries/user/rjbs/has_body/1?long_form=1">Ricardo</a>'s projects, <a href="https://metacpan.org/module/Pod::Weaver">Pod::Weaver</a> a try. Here's the cool stuff I was able to do after not a lot of work.</p>
]]>
        <![CDATA[<p>It's pretty easy to set up your <code>weaver.ini</code> to control how Pod::Weaver does its thing. Like Dist::Zilla, Pod::Weaver has a bunch of PluginBundles to control its behavior according to your specification. The <a href="https://metacpan.org/module/Pod::Weaver::PluginBundle::Default">default bundle</a> gives you a <code>weaver.ini</code> equivalent to this:</p>

<script src="https://gist.github.com/1399038.js?file=gistfile1.txt"></script>

<p>The interesting bit is <code>[Collect / METHODS]</code>. That will find all the POD-like commands called <code>=method</code> in your document, collect the block of text under each, and put them together under a <code>=head1 METHODS</code> section. </p>

<p>So this:</p>

<p><c>
=method foobar</p>

<p>Here is some text</p>

<p>=cut
</c></p>

<p>Becomes this:</p>

<p><c>
=head1 METHODS</p>

<p>=head2 foobar</p>

<p>Here is some text</p>

<p>=cut
</c></p>

<p>That's pretty spiffy, but I wanted to go further. Because Redis::Client has something like 120 methods (each one implements one Redis command) I wanted to organize them under different sections. So I copied-and-pasted the default config into my <code>weaver.ini</code> and modified it thusly:</p>

<script src="https://gist.github.com/1399050.js?file=gistfile1.txt"></script>

<p>The <code>command</code> lines specify the POD-like command to collect into each section. Now, I can use <code>=string_method</code> or <code>=list_method</code> or whatever, and the sections will automatically be collected under the appropriate <code>=head1</code> section when Weaver runs.</p>

<p>But wait, there's more!</p>

<p>Another thing I wanted to do was link each method section to the Redis documentation for that command. It would be really tedious to type <code>L&lt;Redis FOO command|http://example.com/foo&gt;</code> over and over again, so I figured there must be a way for Pod::Weaver to do this. Like Dist::Zilla, it has a very extensible plugin architecture. Also like Dist::Zilla, the docs are somewhat lacking, and I had to dive through a lot of code to figure out what was going on.</p>

<p>I have no idea if the following constitutes "correct" usage of the Pod::Weaver API; I accomplished it mostly through trial-and-error and lots of <code>Dumper</code>ing. But it works.</p>

<script src="https://gist.github.com/1399088.js?file=gistfile1.txt"></script>

<p>The result is that a link like <a href="http://redis.io/commands/lrem">Redis LREM Command</a> gets automatically added to a section that begins <code>=list_method lrem</code>. Very cool!</p>

<p>To use this, I just had to add <code>[-RedisLinks]</code> to my <code>weaver.ini</code>. I'm not sure why the <code>-</code> is required (they're not for Dist::Zilla plugins), but it seems to explode if I omit it.</p>

<p>The plugin is not really useful for anything outside this specific project, but lacking anywhere else to put it, I just stuck it in the Redis-Client distribution, in case someone might find it useful as a reference.</p>

<p>And finally, since this distribution uses Dist::Zilla, to get all this stuff to happen automatically, I just add <code>[PodWeaver]</code> to <code>dist.ini</code>. Voila!</p>
]]>
    </content>
</entry>

<entry>
    <title>Announcing namespace::sweep</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2011/10/announcing-namespacesweep.html" />
    <id>tag:blogs.perl.org,2011:/users/mike_friedman//100.2299</id>

    <published>2011-10-15T23:49:26Z</published>
    <updated>2011-10-16T00:27:51Z</updated>

    <summary>A question recently appeared on Stack Overflow about using namespace::autoclean in conjunction with operator overloading. It turns out that you can&apos;t, because namespace::autoclean, in addition to cleaning up symbols for imported subs, also cleans up the operator magic installed by overload.pm. This had been noticed before, but the suggested fix was rejected in favor of implementing the logic to support overload methods in Class::MOP, which namespace::autoclean uses under the hood to figure out the list of allowed methods for a class, and it doesn&apos;t look like anyone is interested in doing that right now. As it happens, I&apos;m working on a distribution right now which uses Moose and does some operator overloading, so namespace::autoclean would be a problem. I decided that there&apos;s really no reason a symbol-cleaning pragma should depend on Moose (or the MOP) so I wrote namespace::sweep as a replacement. More on the advantages and disadvantages below....</summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    <category term="glob" label="glob" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="moose" label="moose" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="mop" label="mop" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="namespaceautoclean" label="namespace-autoclean" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="oop" label="oop" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="overload" label="overload" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[<p>A <a href="http://stackoverflow.com/questions/7734892/">question</a> recently appeared on Stack Overflow about using namespace::autoclean in conjunction with operator overloading.</p>

<p>It turns out that you can't, because namespace::autoclean, in addition to cleaning up symbols for imported subs, also cleans up the operator magic installed by overload.pm.</p>

<p>This had been <a href="https://rt.cpan.org/Public/Bug/Display.html?id=50938">noticed before</a>, but the <a href="https://github.com/RsrchBoy/namespace-autoclean/commit/344ef42fc3020a5c4b539718fbf1436300f325dd">suggested fix</a> was rejected in favor of implementing the logic to support overload methods in Class::MOP, which namespace::autoclean uses under the hood to figure out the list of allowed methods for a class, and it doesn't look like anyone is interested in doing that right now.</p>

<p>As it happens, I'm working on a distribution right now which uses Moose and does some operator overloading, so namespace::autoclean would be a problem. I decided that there's really no reason a symbol-cleaning pragma should depend on Moose (or the MOP) so I wrote <a href="http://search.cpan.org/~friedo/namespace-sweep/lib/namespace/sweep.pm">namespace::sweep</a> as a replacement. More on the advantages and disadvantages below.</p>
]]>
        <![CDATA[<p><strong>Advantages of namespace::sweep</strong></p>

<ol>
<li>As mentioned above, it won't clobber your overloads.</li>
<li>namespace::sweep provides the same interface as namespace::autoclean, so you should be able to use it as a drop-in replacement.</li>
<li>namespace::sweep passes all of namespace::autoclean's tests, in addition to its own. So there's a reasonable chance that it actually works.</li>
<li>There is no dependance on MOP or Moose, so you can use it for classes built on other frameworks or for which you do not want bulky dependencies. </li>
<li>However, if your class has a Moose (or Moose-compatible) <code>meta</code> object, that will be used to determine the list of methods to keep. Therefore methods composed via roles will Just Work.</li>
<li>The name has the potential for Mr. Miyagi jokes.</li>
</ol>

<p><strong>Disadvantages of namespace::sweep</strong></p>

<ol>
<li>It's new. There are probably problems with it. I haven't used it in anything yet. </li>
<li>It won't work for non-Moose-ish things that add methods to your class, like Mixin.pm or CGI::Application plugins. I have a plan to add a feature that will allow you to exclude symbols from certain classes from being swept, but I haven't written it yet.</li>
<li>Although the dependencies are lighter than namespace::autoclean, it still depends on XS modules including B::Hooks::EndOfScope and Sub::Identify, which can make installation difficult on some platforms.</li>
</ol>

<p>I look forward to hearing your thoughts on this. I'm going to start using it immediately for the project I mentioned above, and I'm sure I will uncover some bugs along the way. The repository is <a href="https://github.com/friedo/perl-namespace-sweep">here</a>.</p>
]]>
    </content>
</entry>

<entry>
    <title>A Pink Camel in the wild</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2011/06/a-pink-camel-in-the-wild.html" />
    <id>tag:blogs.perl.org,2011:/users/mike_friedman//100.1831</id>

    <published>2011-06-06T20:14:11Z</published>
    <updated>2011-06-06T20:17:06Z</updated>

    <summary>Poor camel. Who would do such a cruel thing? Also, that monkey looks like it&apos;s about to take a crap on Amsterdam....</summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[<p>Poor camel. Who would do such a cruel thing?</p>

<img alt="pink_camel.jpg" src="http://blogs.perl.org/users/mike_friedman/pink_camel.jpg" width="720" height="538" class="mt-image-none" style="" />

<p>Also, that monkey looks like it's about to take a crap on Amsterdam.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Here&apos;s a stupid bug.</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2011/04/heres-a-stupid-bug.html" />
    <id>tag:blogs.perl.org,2011:/users/mike_friedman//100.1687</id>

    <published>2011-04-22T21:51:30Z</published>
    <updated>2011-04-22T21:56:47Z</updated>

    <summary>Suppose you want to check if a number is either 70 or 73, and your duct-tape-and-chewing gum production environment is stuck in the stone age without the smart-match operator. You might be tempted to write foo() if $num =~ /^70|73$/, as I did. Oops. That will match 70 and 73, but also anything that ends in 73, like 173 or 273 or foo73. /^(?:70|73)$/ fixes it. The moral of the story: life sucks without smartmatch....</summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[<p>Suppose you want to check if a number is either 70 or 73, and your duct-tape-and-chewing gum production environment is stuck in the stone age without the smart-match operator.</p>

<p>You might be tempted to write <code>foo() if $num =~ /^70|73$/</code>, as I did. Oops. That will match 70 and 73, but also anything that <em>ends</em> in 73, like 173 or 273 or foo73. <code>/^(?:70|73)$/</code> fixes it.</p>

<p>The moral of the story: life sucks without smartmatch. </p>
]]>
        

    </content>
</entry>

<entry>
    <title>Introducing App::htrepl</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2011/02/introducing-apphtrepl.html" />
    <id>tag:blogs.perl.org,2011:/users/mike_friedman//100.1512</id>

    <published>2011-02-28T05:43:18Z</published>
    <updated>2011-02-28T07:40:44Z</updated>

    <summary>I&apos;ve released a (very preliminary) development release of a new project, App::htrepl, a commandline REPL for more easily debugging HTTP applications. It was inspired by a similar project for Node.js, the link to which I can&apos;t find at the moment. You can find the repository at github here, and it will be hitting your local CPAN mirror soon. REPL means read-eval-print loop. App::htrepl provides a commandline script, htrepl, which makes it easier to talk to your HTTP applications. The only dependencies are LWP and Term::ReadLine; the code is otherwise designed to be as lean as possible. Here are some examples of how it can be used:...</summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    <category term="perllwphttprepl" label="perl lwp http repl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[<p>I've released a (very preliminary) development release of a new project, App::htrepl, a commandline REPL for more easily debugging HTTP applications. It was inspired by a similar project for Node.js, the link to which I can't find at the moment. You can find the repository at github <a href="https://github.com/friedo/app-htrepl">here</a>, and it will be hitting your local CPAN mirror soon.</p>

<p>REPL means read-eval-print loop. App::htrepl provides a commandline script, <code>htrepl</code>, which makes it easier to talk to your HTTP applications. The only dependencies are LWP and Term::ReadLine; the code is otherwise designed to be as lean as possible.</p>

<p>Here are some examples of how it can be used:</p>
]]>
        <![CDATA[<p>Start <code>htrepl</code> from the commandline.</p>

<pre><code>$ htrepl 
htrepl&gt; head http://www.friedo.com/
Setting protocol http
Setting host www.friedo.com
Setting port 80


HEAD http://www.friedo.com:80//

200 OK
Connection: close
Date: Sun, 27 Feb 2011 21:23:14 GMT
Accept-Ranges: bytes
ETag: "ff1f6-88e-87f72640"
Server: Apache/2.2.4 (Fedora)
Content-Length: 2190
Content-Type: text/html; charset=UTF-8
Last-Modified: Tue, 16 Mar 2010 23:41:05 GMT
Client-Date: Mon, 28 Feb 2011 05:54:06 GMT
Client-Peer: 206.71.179.40:80
Client-Response-Num: 1
</code></pre>

<p><code>htrepl</code> automatically determines the Host header and port name, and other details, which it remembers for subsequent requests.</p>

<pre><code>htrepl&gt; get /foobar


GET http://www.friedo.com:80//foobar

404 Not Found
Connection: close
Date: Sun, 27 Feb 2011 21:23:45 GMT
Server: Apache/2.2.4 (Fedora)
Content-Length: 283
Content-Type: text/html; charset=iso-8859-1
Client-Date: Mon, 28 Feb 2011 05:54:36 GMT
Client-Peer: 206.71.179.40:80
Client-Response-Num: 1
Title: 404 Not Found

&lt;!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"&gt;
&lt;html&gt;&lt;head&gt;
&lt;title&gt;404 Not Found&lt;/title&gt;
&lt;/head&gt;&lt;body&gt;
&lt;h1&gt;Not Found&lt;/h1&gt;
&lt;p&gt;The requested URL /foobar was not found on this server.&lt;/p&gt;
&lt;hr&gt;
&lt;address&gt;Apache/2.2.4 (Fedora) Server at www.friedo.com Port 80&lt;/address&gt;
&lt;/body&gt;&lt;/html&gt;
</code></pre>

<p>If you only want to look at headers, you can throw away the response body:</p>

<pre><code>htrepl&gt; .hide body
Hiding body

htrepl&gt; get /foobar


GET http://www.friedo.com:80//foobar

404 Not Found
Connection: close
Date: Sun, 27 Feb 2011 21:25:51 GMT
Server: Apache/2.2.4 (Fedora)
Content-Length: 283
Content-Type: text/html; charset=iso-8859-1
Client-Date: Mon, 28 Feb 2011 05:56:42 GMT
Client-Peer: 206.71.179.40:80
Client-Response-Num: 1
Title: 404 Not Found
</code></pre>

<p>And you can even turn off headers:</p>

<pre><code>htrepl&gt; .hide headers
Hiding headers

htrepl&gt; get /foobar


GET http://www.friedo.com:80//foobar

404 Not Found
</code></pre>

<p><code>htrepl</code> allows you to set arbitrary headers, User-Agent strings (the default is "<code>perl-htrepl/$VERSION</code>") and cookies.</p>

<pre><code>htrepl&gt; .header x-foobar-header blah blah
Setting header x-foobar-header =&gt; blah blah
</code></pre>

<p>On subsequent requests, the <code>x-foobar-header</code> will be sent, until it's deleted.</p>

<pre><code>htrepl&gt; .cookie mycookie 12345
Setting cookie mycookie =&gt; 12345
</code></pre>

<p>This saves a cookie in the session, and it will be sent to subsequent requests to the same host. You can inspect your cookies, including those sent from HTTP servers:</p>

<pre><code>htrepl&gt; .show headers
Showing headers

htrepl&gt; get http://www.google.com/
Setting host www.google.com

GET http://www.google.com:80//

200 OK
Cache-Control: private, max-age=0
Connection: close
Date: Mon, 28 Feb 2011 06:02:03 GMT
Server: gws
Content-Type: text/html; charset=ISO-8859-1
Expires: -1
Client-Date: Mon, 28 Feb 2011 06:02:03 GMT
Client-Peer: 72.14.204.104:80
Client-Response-Num: 1
Set-Cookie: PREF=ID=f322e9c1e288ae57:U=2a0bdbd0aa3bc510:FF=0:TM=1298872863:LM=1298872923:S=jMevxo0BYrps9-T2; expires=Wed, 27-Feb-2013 06:02:03 GMT; path=/; domain=.google.com
Title: Google
X-XSS-Protection: 1; mode=block

htrepl&gt; .look cookie PREF
PREF: ID=f322e9c1e288ae57:U=2a0bdbd0aa3bc510:FF=0:TM=1298872863:LM=1298872923:S=jMevxo0BYrps9-T2
</code></pre>

<p>If the method name is <code>POST</code> or <code>PUT</code>, <code>htrepl</code> will prompt you for the message data:</p>

<pre><code>htrepl&gt; put /
Enter PUT body data. Terminate with CTRL-d

PUT&gt; blah
PUT&gt; blah blah
PUT&gt; 

PUT http://www.friedo.com:80//

405 Method Not Allowed
Connection: close
Date: Sun, 27 Feb 2011 23:08:08 GMT
Server: Apache/2.2.4 (Fedora)
Allow: GET,HEAD,POST,OPTIONS,TRACE
Content-Length: 310
Content-Type: text/html; charset=iso-8859-1
Client-Date: Mon, 28 Feb 2011 07:38:59 GMT
Client-Peer: 206.71.179.40:80
Client-Response-Num: 1
Title: 405 Method Not Allowed
</code></pre>

<p>You can even load message data from a file:</p>

<pre><code>htrepl&gt; put /foobar &lt; /path/to/some/file.dat
</code></pre>

<p>There's also a <code>.help</code> command which will explain most of the commands available. Anything not beginning with a dot is assumed to be an HTTP method name and URI to execute it upon.</p>

<p><strong>TODO:</strong></p>

<p>A lot. There are some bugs with URL-handling that need to be fixed. Support for saving cookies and prefs to disk would be nice. Expanding the docs (there is basically none right now) and cleaning up some of the code would be nice. All patches/pull requests are welcome.</p>
]]>
    </content>
</entry>

<entry>
    <title>The Oft-Overlooked and the Sometimes-Neverused</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2011/01/the-oft-overlooked-and-the-sometimes-neverused.html" />
    <id>tag:blogs.perl.org,2011:/users/mike_friedman//100.1348</id>

    <published>2011-01-11T19:09:08Z</published>
    <updated>2011-01-11T19:25:40Z</updated>

    <summary>Perl has so many useful builtins that most people who use the language probably only use a fraction of what&apos;s available. Every year or so I like to peruse perlfunc and perlsyn as a refresher. Yet in years and years of hacking Perl code, there are a few in there that I will never use. I surprised myself the other day by reaching for the loop control command redo. It occurred to me that while I use other loop controlling things like next and last constantly, I couldn&apos;t remember a single time before when I have ever had to redo an iteration. For the curious, here&apos;s the astonishingly simple scenario where it came up....</summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    <category term="perlloopscontrolflow" label="perl loops control-flow" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[<p>Perl has so many useful builtins that most people who use the language probably only use a fraction of what's available. Every year or so I like to peruse <a href="http://perldoc.perl.org/perlfunc.html">perlfunc</a> and <a href="http://perldoc.perl.org/perlsyn.html">perlsyn</a> as a refresher. Yet in years and years of hacking Perl code, there are a few in there that I will never use. I surprised myself the other day by reaching for the loop control command <code>redo</code>. It occurred to me that while I use other loop controlling things like <code>next</code> and <code>last</code> constantly, I couldn't remember a single time before when I have ever had to redo an iteration. For the curious, here's the astonishingly simple scenario where it came up.</p>]]>
        <![CDATA[<p>When you're writing applications against Twitter's REST API, they ask you to be polite and only execute a certain number of HTTP requests in a certain amount of time. The certain number depends on their current server load, and so you can't just set a time limit in your script and forget it. Instead, you have to make your requests and then pause if Twitter asks you to slow down. If they want you to ease back on the throttle, they send a custom HTTP status with a header indicating how many seconds you should wait. Here's how I handle it.</p>

<p><code><br />
    foreach my $tag( keys %tags ) {<br />
        ....<br />
        my $res = $ua->get( $url );<br />
        unless( $res->is_success ) { <br />
            my $status = $res->code;<br />
            if ( $status == 420 ) { <br />
                # we are being rate-limited<br />
                my $wait = $res->header( 'Retry-After' ) || 31;<br />
                warn "API rate-limit - waiting for $wait secs...";<br />
                sleep $wait;<br />
                redo;<br />
            }<br />
            ....<br />
       }</p>

<p>        my $json = $res->decoded_content;<br />
        ....<br />
     }<br />
</code></p>

<p>This loops over a bunch of Twitter hash tags and asks for some information about each one. If Twitter gets antsy, instead of sending the information with a HTTP status of 200, it sends a "slow down" message with an HTTP status of 420. The script sits there and does nothing for the allotted number of seconds and then repeats the loop iteration to hopefully get the information that resulted in an error last time.</p>

<p>What language features have you never used, despite being aware of them, or were surprised to use for the first time after much experience?</p>]]>
    </content>
</entry>

<entry>
    <title>Not Quite Getting It</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2010/07/not-quite-getting-it.html" />
    <id>tag:blogs.perl.org,2010:/users/mike_friedman//100.774</id>

    <published>2010-07-20T23:25:21Z</published>
    <updated>2010-07-20T23:33:54Z</updated>

    <summary>Stories of obfuscated Perl written by incompetent people (or sadists) are legion. But sometimes you come across some code that appears as if it was mostly written by someone who knew what they were doing, but seemed to be missing some crucial bit of information. Today I saw a set of OO Perl packages that appeared perfectly cromulent, until I noticed that every method call looked like this:...</summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    <category term="obfu" label="obfu" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="oop" label="oop" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="weird" label="weird" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[<p>Stories of obfuscated Perl written by incompetent people (or sadists) are legion. But sometimes you come across some code that appears as if it was mostly written by someone who knew what they were doing, but seemed to be missing some crucial bit of information.</p>

<p>Today I saw a set of OO Perl packages that appeared perfectly cromulent, until I noticed that <em>every</em> method call looked like this:</p>]]>
        <![CDATA[<p><code><br />
sub foo { <br />
    ...<br />
    $self->{args} = [ 1, 2, 3 ];<br />
    $self->method;<br />
}<br />
sub method { <br />
    my $self = shift;<br />
    my @args = @{ $self->{args} };<br />
    ...<br />
}<br />
</code></p>

<p>The rest of the code was clear, well-structured, logically modularized, and even unit-tested. Apparently, this otherwise perfectly good programmer was either completely unaware that Perl methods can take parameters, or, for reasons that are lost to the mists of time, chose not to use them.</p>

<p>Weird.</p>]]>
    </content>
</entry>

<entry>
    <title>Measure Twice, Cut Once</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2010/05/measure-twice-cut-once.html" />
    <id>tag:blogs.perl.org,2010:/users/mike_friedman//100.581</id>

    <published>2010-05-24T05:23:14Z</published>
    <updated>2010-05-24T05:23:39Z</updated>

    <summary>Good advice for both building a house and performing a database update....</summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[<p>Good advice for both building a house and performing a database update.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Starting Over from Scratch</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2010/05/starting-over-from-scratch.html" />
    <id>tag:blogs.perl.org,2010:/users/mike_friedman//100.578</id>

    <published>2010-05-23T07:39:39Z</published>
    <updated>2010-05-23T07:48:26Z</updated>

    <summary>From Lee Harris&apos;s circuitous polemic Civilization and Its Enemies: The Next Stage of History: The error of abstract reason is, in short, forgetfulness. It forgets that its abstractions are designed to try to capture the infinitely elusive real. It begins to use these same abstractions as yardsticks by which to judge the real. Harris was summarizing a lengthy criticism of Enlightenment-era political thought, and the failure of the various radical philosophies that attempted to wipe away and reconstruct society from the ground up. I find the same lesson applies to good software: it&apos;s often imperfect, but those imperfections are there because reality demands them, and scrapping a working, if imperfect solution in favor of building a new one inspired by a new abstraction is a project often doomed to failure....</summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[<p>From Lee Harris's circuitous polemic <em>Civilization and Its Enemies: The Next Stage of History</em>:<br />
<blockquote>The error of abstract reason is, in short, forgetfulness. It forgets that its abstractions are designed to try to capture the infinitely elusive real. It begins to use these same abstractions as yardsticks by which to judge the real.<br />
</blockquote><br />
Harris was summarizing a lengthy criticism of Enlightenment-era political thought, and the failure of the various radical philosophies that attempted to wipe away and reconstruct society from the ground up. I find the same lesson applies to good software: it's often imperfect, but those imperfections are there because reality demands them, and scrapping a working, if imperfect solution in favor of building a new one inspired by a new abstraction is a project often doomed to failure.</p>]]>
        
    </content>
</entry>

<entry>
    <title>DBIx::Class Anti-Verbosity</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/mike_friedman/2010/04/dbixclass-anti-verbosity.html" />
    <id>tag:blogs.perl.org,2010:/users/mike_friedman//100.501</id>

    <published>2010-04-24T03:40:10Z</published>
    <updated>2010-04-24T04:01:42Z</updated>

    <summary><![CDATA[Every time I set up a DBIx::Class schema for a project, I find myself re-implementing the same pattern. While DBIC is one of the great things about modern Perl, it requires a lot of typing. Whenever I want to grab some stuff from a table, it's my @records = $schema-&gt;resultset( 'CamelCasedClassName' )-&gt;search( ... ); Today, I used DBIx::Class::Schema::Loader to auto-generate a schema for a fun little 182-table database. I ended up with modules with names like MyApp::DBIC::Result::XStreamQueryParentArticle and MyApp::DBIC::Result::ArticleElementContent and so forth. Very useful, but what painful nomenclature. So I ended up doing the same little hack that I always do, but improved upon it a bit this time, and have finally arrived at a solution that I really like....]]></summary>
    <author>
        <name>Mike Friedman</name>
        <uri>http://www.friedo.com/</uri>
    </author>
    
    <category term="perldbixclass" label="perl dbixclass" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/mike_friedman/">
        <![CDATA[<p>Every time I set up a <a href="http://search.cpan.org/dist/DBIx-Class/">DBIx::Class</a> schema for a project, I find myself re-implementing the same pattern. While DBIC is one of the great things about modern Perl, it requires a <em>lot</em> of typing. Whenever I want to grab some stuff from a table, it's</p>

<pre><code>my @records = $schema-&gt;resultset( 'CamelCasedClassName' )-&gt;search( ... );
</code></pre>

<p>Today, I used DBIx::Class::Schema::Loader to auto-generate a schema for a fun little 182-table database. I ended up with modules with names like <code>MyApp::DBIC::Result::XStreamQueryParentArticle</code> and <code>MyApp::DBIC::Result::ArticleElementContent</code> and so forth. Very useful, but what painful nomenclature.</p>

<p>So I ended up doing the same little hack that I always do, but improved upon it a bit this time, and have finally arrived at a solution that I really like.</p>
]]>
        <![CDATA[<p>First, I modified my main DBIC class to instantiate the schema and wrap that up in a little object for which there is a simple constructor.</p>

<pre><code>sub new { 
    my $class = shift;
    my %args = 
      ( type =&gt; 'master',
        @_
      );

    # ... bunch of config stuff here

    my $dsn = sprintf 'dbi:mysql:%s;host=%s', $db, $host;

    my $schema = $class-&gt;connect( $dsn, $user, $pass );

    $args{schema} = $schema;

    return bless \%args;
}
</code></pre>

<p>Then I added a loop to load up some shortcut methods when the module starts up:</p>

<pre><code>foreach my $source ( __PACKAGE__-&gt;sources ) { 
    my $source_class = 'MyApp::DBIC::Result::' . $source;
    my $tbl = $source_class-&gt;table;

    no strict 'refs';
    *{ 'MyApp::DBIC::rs_' . $tbl } = sub {
        my $self = shift;
        return $self-&gt;{schema}-&gt;resultset( $source );
    };
}
</code></pre>

<p>Now, instead of writing </p>

<pre><code>my $schema = MyApp::DBIC-&gt;connect( ... );
my @records = $schema-&gt;resultset( 'OmnitureArticlePopularity' )-&gt;search( ... )
</code></pre>

<p>I can write</p>

<pre><code>my $db = MyApp::DBIC-&gt;new( type =&gt; 'master' );
my @records = $db-&gt;rs_omniture_article_popularity-&gt;search( ... )
</code></pre>

<p>The auto-generated method names all come from the DB's table names (prepended with <code>rs_</code> ) which are much easier to remember, and easier to type, than the CamelCased module names. The <code>$db</code> object also keeps track of some useful data about our environment, where there are multiple dev/stage/production databases and abstracts away the configuration.</p>
]]>
    </content>
</entry>

</feed>
