<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>House Absolute(ly Pointless)</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/" />
    <link rel="self" type="application/atom+xml" href="http://blog.urth.org/atom.xml" />
    <id>tag:blog.urth.org,2008-08-19://2</id>
    <updated>2010-01-15T17:04:26Z</updated>
    <subtitle>Unsubstantiated Opinions and Meaningless Blather</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.3-en</generator>

<entry>
    <title>Moose Class in Minneapolis - Friday, February 5, 2009</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2010/01/moose-class-in-minneapolis-friday-february-5-2009.html" />
    <id>tag:blog.urth.org,2010://2.127</id>

    <published>2010-01-15T16:56:57Z</published>
    <updated>2010-01-15T17:04:26Z</updated>

    <summary>I&apos;m doing my one-day Moose class here in Minneapolis again, as part of Frozen Perl. The class is even cheaper this time, as a special deal for the workshop. It&apos;s a mere $100 per person! The class is an interactive...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p>I'm doing my one-day Moose class here in Minneapolis again, as part of <a href="http://frozen-perl.org">Frozen Perl</a>. The class is even cheaper this time, as a special deal for the workshop. It's a mere $100 per person!</p>

<p>The class is an interactive course, meaning you bring your laptop and do exercises in between lecture sections. It covers all the basics of Moose, and even gets into some of the more advanced bits.</p>

<p>Here's what students who took the class back in September said:</p>

<ul>
<li>"The exercises were awesome!  I really love how they were set up as test cases--there is really no other way to give this much feedback!" - wu</li>
<li>"Using the test framework to drive the exercises was brilliant, providing feedback and building confidence. The exercises weren't too difficult, and the detailed, step-by-step instructions helped to make them friendly." - Ken O</li>
</ul>

<p>You can sign up and pay for the class at the <a href="http://frozen-perl.org">Frozen Perl</a> site. I'd also encourage you to join us for the workshop the next day. There's a good slate of presentations scheduled, and it should be a lot of fun.</p>

<p>Finally, on Sunday, February 7, we'll be having a hackathon. See the Frozen Perl site for details.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Project Stack Push/Pop</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2009/12/project-stack-pushpop.html" />
    <id>tag:blog.urth.org,2009://2.121</id>

    <published>2009-12-02T22:26:54Z</published>
    <updated>2009-12-02T23:08:27Z</updated>

    <summary>I have an amazing ability to get distracted from my goals when programming. Sometimes it feels like each project I work on is just the latest distraction from what I was working on. Usually this happens because I&apos;m happily hacking...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p>I have an amazing ability to get distracted from my goals when
programming. Sometimes it feels like each project I work on is just the latest
distraction from what I <strong>was</strong> working on. Usually this happens because I'm
happily hacking away on project A until I hit a roadblock. That roadblock
might be a missing feature in a module I'm using, or maybe a module I need
that doesn't exist. Sometimes the roadblock is a gap in my understanding. I
don't know how to do what I want in a satisfactory way, so I need to learn
more about a tool, or just experiment with ways to approach the problem.</p>

<p>I push a new project onto the stack and off I go. I don't know how deep the
stack is now. There's probably items that were on ther long ago that have
already been forgotten.</p>

<p>Here's an example of where I am in my stack right now:</p>


<ul>
  <li>
    <p>
      Working on [VegGuide](http://www.vegguide.org) and other things, I've
      become thoroughly sick of Alzabo ...
    </p>
    <ul>
      <li>
        <p>
          so I play with DBIx::Class but it doesn't grab me ...
        </p>
      </li>
      <li>
        <p>
          I write <a href="http://search.cpan.org/dist/Fey-ORM">Fey::ORM</a> ...
        </p>
      </li>
    </ul>
  </li>
  <li>
    <p>
      and back to VegGuide, but I really don't like a lot of things about it,
      I need to explore new ways of writing webapps ...
    </p>
    <ul>
      <li>
        <p>
          I start working on a <a href="http://hg.urth.org/hg/R2">new webapp</a>, a
          donor/volunteer management app for nonprofits. By building an app
          from scratch I can get a better understanding of how I want to write
          moderm webapps. But this type of app is rather complicated so ...
        </p>
        <ul>
          <li>
            <p>
              having been unhappy with <a href="http://mojomojo.org/">MojoMojo</a>, I
              start working on a <a href="http://hg.urth.org/hg/Silki">wiki</a> designed
              for non-geeks (target audience, my animal rights group). I'm
              using Markdown as the wikitext language, but the existing
              Markdown tools in Perl don't do what I want so ...
            </p>
            <ul>
              <li>
                <p>
                  I write <a href="http://search.cpan.org/dist/Markdent">Markdent</a>.
                </p>
              </li>
            </ul>
          </li>
          <li>
            <p>
              now I'm running into major issues with <a href="http://search.cpan.org/dist/HTML-WikiConverter">HTML::WikiConverter</a>,
              which I use to turn GUI-generated HTML back to Markdown. The
              temptation to fix/rewrite is strong ...
            </p>
            <ul>
              <li>
                <p>
                  sigh
                </p></li>
            </ul></li>
        </ul></li>
    </ul></li>
</ul>Of course, it's not really quite as simple as this might imply. It's not like the <i>only</i> reason for working on a donor management application is to explore webapps. It's useful all on its own.<br /><br />Even scarier is the fact that there are other unrelated projects that keep trying to intrude, like making ACT run on mod_perl2 so I can upgrade my server from Dapper to Hardy. I've managed to put that one off for a while, at least, but it keeps nagging at me.<br /><br />My capacity for adding projects to my stack is simultaneously impressive and disturbing. There's no problem so compelling that it can't be superceded by a new problem uncovered in the course of solving the original.<br /><br />
]]>
        
    </content>
</entry>

<entry>
    <title>What&apos;s the Point of Markdent?</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2009/11/whats-the-point-of-markdent.html" />
    <id>tag:blog.urth.org,2009://2.119</id>

    <published>2009-11-28T16:40:03Z</published>
    <updated>2009-12-03T16:38:53Z</updated>

    <summary>Markdent is my new event-driven Markdown parser toolkit, but why should you care? First, let&apos;s talk about Markdown. Markdown is yet another wiki-esque format for marking up plain text. What makes Markdown stand out is it&apos;s emphasis on usability and...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p><a href="http://search.cpan.org/dist/Markdent">Markdent</a> is my new event-driven
Markdown parser toolkit, but why should you care?</p>

<p>First, let's talk about Markdown. Markdown is yet another wiki-esque format
for marking up plain text. What makes Markdown stand out is it's emphasis on
usability and "natural" usage. It's syntax is based on things people have been
doing to "mark up" plain text email for years.</p>

<p>For example, if you wanted to list some items in a plain text email, you'd
wite something like:</p>

<pre><code>* List item 1
* List item 2
* List item 3
</code></pre>

<p>Well, this is how it works in Markdown too. Want to emphasize some text?
*Wrap it in asterisks* or _underscores_.</p>

<p>So why do you need an event-driven parser toolkit for dealing with Markdown?
CPAN already has several modules for dealing with Markdown, most notably
<a href="http://search.cpan.org/dist/Text-Markdown">Text::Markdown</a>.</p>

<p>The problem with Text::Markdown is that all you can do with it is generate
HTML, but there's so much more you could do with a Markdown document.</p>

<p>If you're using Markdown for an application (like a wiki), you may need to
generate slightly different HTML for different users. For example, maybe
logged-in users see documents differently.</p>

<p>But what if you want to cache parsing in order to speed things up? If you're
going straight from Markdown to HTML, you'd need to cache the resulting HTML
for each type of user (or even for each individual user in the worst case).</p>

<p>With Markdent, you can cache an intermediate representation of the document as
a stream of events. You can then replay this stream back to the HTML generator
as needed.</p>

<h3>What's the Impact of Caching?</h3>

<p>Here's a benchmark comparing three approaches.</p>

<ol>
<li>Use Markdent to parse the document and generate HTML from scratch each time.</li>
<li>Use Text::Markdown</li>
<li>Use Markdent to parse the document once, then use Storable to store the
event stream. When generating HTML, thaw the event stream and replay it back
to the HTML generator.</li>
</ol>

<table>
  <thead>
    <tr>
      <th></th>
      <th>Rate</th>
      <th>parse from scratch</th>
      <th>Text::Markdown</th>
      <th>replay from captured events</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>parse from scratch</th>
      <td>1.07/s</td>
      <td>--</td>
      <td>-67%</td>
      <td>-83%</td>
    </tr>
    <tr>
      <th>Text::Markdown</th>
      <td>3.22/s</td>
      <td>202%</td>
      <td>--</td>
      <td>-48%</td>
    </tr>
    <tr>
      <th>replay from captured events</th>
      <td>6.13/s</td>
      <td>475%</td>
      <td>91%</td>
      <td>--</td>
    </tr>
  </tbody>
</table>

<p>This benchmark is <a href="http://cpansearch.perl.org/src/DROLSKY/Markdent-0.07/bench/capture-vs-parse">included in the Markdent
distro</a>. One
feature to note about this benchmark is that it parses 23 documents from the
<a href="http://git.michelf.com/mdtest/">mdtest test suite</a>. Those documents are
mostly pretty short.</p>

<p>If I benchmark just the largest document in mdtest, the numbers change a bit:</p>

<table>
  <thead>
    <tr>
      <th></th>
      <th>Rate</th>
      <th>parse from scratch</th>
      <th>Text::Markdown</th>
      <th>replay from captured events</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>parse from scratch</th>
      <td>2.32/s</td>
      <td>--</td>
      <td>-58%</td>
      <td>-84%</td>
    </tr>
    <tr>
      <th>Text::Markdown</th>
      <td>5.52/s</td>
      <td>138%</td>
      <td>--</td>
      <td>-63%</td>
    </tr>
    <tr>
      <th>replay from captured events</th>
      <td>14.8/s</td>
      <td>538%</td>
      <td>168%</td>
      <td>--</td>
    </tr>
  </tbody>
</table>

<p>Markdent probably speeds up on large documents because each new parse requires
constructing a number of objects. With 23 documents we construct those objects
23 times. When we parse one document the actual speed of parsing becomes more
important, as does the speed of <em>not</em> parsing.</p>

<h3>What Else?</h3>

<p>But there's more to Markdent than caching. One feature that a lot of wikis
have is "backlinks", which is a list of pages linking to the current
page. With Markdent, you can write a handler that <em>only</em> looks at links. You
can use this to capture all the links and generate your backlink list.</p>

<p>How about a full text search engine? Maybe you'd like to give a little more
weight to titles than other text. You can write a handler which collects title
text and body text separately, then feed that into your full text search tool.</p>

<p>There's a theme here, which is that Markdent makes document <em>analysis</em> much
easier.</p>

<p>That's not all you can do. What about a Markdown-to-Textile converter? How
about a Markdown-to-Markdown converter for canonicalization?</p>

<p>Because Markdent is modular and pluggable, if you can think of it, you can
probably do it.</p>

<p>I haven't even touched on extending the parser itself. That's still a much
rougher area, but it's not that hard. The Markdent distro includes an
implementation of a <a href="http://search.cpan.org/dist/Markdent/lib/Markdent/Dialect/Theory.pod">dialect called
"Theory"</a>,
based on some Markdown extension proposals by David Wheeler.</p>

<p>This dialect is implemented by subclassing the Standard dialect parser
classes, and providing some additional event classes to represent table
elements.</p>

<p>I hope that other people will pick up on Markdent and write their own dialects
and handlers. Imagine a rich ecosystem of tools for Markdown comparable to
what's available for XML or HTML. This would make an already useful markup
language even more useful.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Want Good Tools? Break Your Problems Down</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2009/11/want-good-tools-break-your-problems-down.html" />
    <id>tag:blog.urth.org,2009://2.118</id>

    <published>2009-11-27T21:12:19Z</published>
    <updated>2009-11-27T22:09:44Z</updated>

    <summary>I&apos;ve been working a new a project recently, Markdent, an event-driven Markdown parser toolkit. Why? Because the existing Perl Markdown tools just aren&apos;t flexible enough. They bundle up Markdown parsing with HTML conversion all in one API, and I need...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p>I've been working a new a project recently,
<a href="http://search.cpan.org/dist/Markdent">Markdent</a>, an event-driven Markdown
parser toolkit.</p>

<p>Why? Because the existing Perl Markdown tools just aren't flexible
enough. They bundle up Markdown parsing with HTML conversion all in one API,
and I need to do more than convert to HTML.</p>

<p>This sort of inflexibility is quite common when I look at CPAN
libraries. Looking back at the Perl DateTime Project, one of my big problems
with all the other date/time modules on CPAN was their lack of flexibility. If
I could have added good time zone handling to an existing project way back
then, I probably would have, but I couldn't, and the <a href="http://datetime.perl.org">Perl DateTime
Project</a> was born.</p>

<p>If there is one point I would hammer home to all module authors, it would be
"solve small problems". I think that the failure to do this is what leads to
the inflexibility and tight coupling I see in so many CPAN distributions.</p>

<p>For example, I imagine that in the date/time world some people thought "I need
a bunch of date math functions" or "I need to parse lots of possible date/time
strings". Those are good problems to solve, but by going straight there you
lose any hope of a good API.</p>

<p>Similarly, with Markdown parsers, I imagine that someone though "I'd like to
convert Markdown to HTML", so they wrote a module that does just that.</p>

<p>I can't really fault their goal-focused attitudes. Personally, I sometimes
find myself getting lost in digressions. For example, I'm currently writing a
webapp with the goal of exploring techniques I want to use in <em>another</em>
webapp!</p>

<p>But there's a lot to be said for not going straight to your goal. I'm a big
fan of breaking a problem down into smaller pieces and solving each piece
separately.</p>

<p>For example, when it comes to Markdown, there are several distinct steps on
the way from Markdown to HTML. First, we need to be able to parse
Markdown. Parsing Markdown is a step of its own. <em>Then</em> we need to take the
results of parsing and turn it into HTML.</p>

<p>If we think of the problem as consisting of these pieces, a clear and flexible
design emerges. We need a tool for parsing Markdown (a parser). Separately, we
need a tool for converting parse results to HTML (a converter or parse result
handler).</p>

<p>Now we need a way to connect these pieces. In the case of Markdent, the
connection is an event-driven API where each event is an object and the event
receiver conforms to a known API.</p>

<p>It's easy to put these two things together and make a nice <a href="http://search.cpan.org/dist/Markdent/lib/Markdent/Simple.pm">simple
Markdown-to-HTML
converter</a>.</p>

<p>But since I took the time to break the problem down, you can <em>also</em> do other
things with this tool. For example, I can do something else with our parse
results, like capture all the links or cache the intermediate result of the
parsing (an event stream).</p>

<p>And since the HTML generator is a small piece, I can also reuse that. Now that
I've cached our event stream, I can pull it from the cache later and use it to
generate HTML without re-parsing the document. In the case of Markdent, using
a cached parse result to generate HTML was about six times faster in my
benchmarks!</p>

<p>Because Markdent has small pieces, there are all sorts of interesting ways to
reuse them. How about a Markdown-to-Textile converter? Or how about adding a
<a href="http://search.cpan.org/dist/Markdent/lib/Markdent/Role/FilterHandler.pm">filter</a>
which <a href="http://search.cpan.org/dist/Markdent/lib/Markdent/Handler/HTMLFilter.pm">doesn't allow any raw
HTML</a>?</p>

<p>We've all heard that loose coupling makes good APIs. But just saying that
doesn't really help you understand how to achieve loose coupling. Loose
coupling comes from breaking a big problem down into small independent
problems.</p>

<p>As you solve each problem, think about how those solutions will
communicate. Design a simple API or communications protocol. You'll know the
API is simple enough if you can imagine <em>easily</em> swapping out each piece of
the problem with another API-conformant piece. A loosely coupled API is one
that makes replacing one end of the API easy.</p>

<p>And best of all, when you break problems down into loosely coupled pieces,
you'll make it <em>much</em> easier for others to contribute to and extend your
tools. Moose is a great example of this. It's fancy sugar layer exists on top
of loosely coupled units known as the metaclass protocol. By separating the
sugar from the underlying pieces, we've enabled others to create a <a href="http://search.cpan.org/search?query=moosex&amp;mode=dist">huge
number of Moose
extensions</a>.</p>

<p>The same goes for the Perl DateTime Project. I wrote the core pieces, but
there have been <a href="http://search.cpan.org/search?query=datetime&amp;mode=dist">many, many great
contributions</a>. This
wealth of extensions wouldn't be possible without the loosely coupled core
pieces and a <a href="http://datetime.perl.org/?Developers">well-defined API</a> for
communicating between components.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Support Me in a Leaflet-a-thon</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2009/10/support-me-in-a-leaflet-a-thon.html" />
    <id>tag:blog.urth.org,2009://2.115</id>

    <published>2009-10-10T15:57:19Z</published>
    <updated>2009-10-10T16:00:57Z</updated>

    <summary>First off, there&apos;s no technical content in this blog post. Sorry. I&apos;ll be participating in a leaflet-a-thon next week with my animal advocacy group, Compassionate Action for Animals. This is like a walkathon, but with less walking and more handing...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="AR-Veg" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Personal" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p>First off, there's no technical content in this blog post. Sorry.</p>

<p>I'll be participating in a leaflet-a-thon next week with my animal advocacy group, <a href="http://www.exploreveg.org">Compassionate Action for Animals</a>. This is like a walkathon, but with less walking and more handing stuff out.</p>

<p>To those within the light of my pixels, if you'd like to support me, you can do so by <a href="http://firstgiving.com/caa">making a donation online</a>. Even if you don't particularly support the cause, please consider doing this to support <em>me</em>. If you've used a module I've written, you could say thanks by making a donation.</p>

<p>Thanks,</p>

<p>-dave</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Moose Class in Minneapolis - September 23, 2009</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2009/09/moose-class-in-minneapolis-september-23-2009.html" />
    <id>tag:blog.urth.org,2009://2.112</id>

    <published>2009-09-03T18:25:20Z</published>
    <updated>2009-09-03T18:33:54Z</updated>

    <summary>The class is scheduled for Wednesday, September 23, 2009, from 8:30am to 5:00pm. The class will be at the Days Inn in Minneapolis near the U of MN campus. There is free on-site parking at the hotel. The class will...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p>The class is scheduled for Wednesday, September 23, 2009, from 8:30am to 5:00pm. The class will be at the <a href="http://maps.google.com/maps?oe=utf-8&amp;client=firefox-a&amp;ie=UTF8&amp;q=days+inn+minneapolis&amp;fb=1&amp;split=1&amp;gl=us&amp;cid=0,0,501824200097184849&amp;ei=WAqgStK-KYukMbT0nd8P&amp;z=16&amp;iwloc=A">Days Inn in Minneapolis</a> near the U of MN campus. There is free on-site parking at the hotel.</p>

<p>The class will run all day, with an hour or so lunch break. I will not be serving food or drinks, but you are welcome to bring your own, of course.</p>

<p>In order to attend, you must register in advance. You can <a href="https://www.theperlreview.com/cgi-bin/events.cgi">register through the Perl Review</a> and pay online. The class costs $120 per person. This is a very low introductory rate, and future classes will cost substantially more, so take advantage of this opportunity while you can.</p>

<p>Enrollment is limited to 16 people in total.</p>

<p>Here's the full class description ....</p>

<h2>Intro to Moose</h2>

<p>Join us for an interactive hands-on course all about Moose. Moose is an OO system for Perl 5 that provides a simple declarative layer of "sugar" on top of a powerful, extensible meta-model.</p>

<p>With Moose, simple classes can be created without writing any subroutines, and complex classes can be simplified. Moose's features include a powerful attribute declaration system, type constraints and coercions, method modifiers ("before", "after", and "around"), a role system (like mixins on steroids), and more. Moose also has a vibrant ecosystem of extensions as seen in the variety of MooseX:: modules on CPAN.</p>

<p>This course will cover Moose's core features, dip a toe into the meta-model, and explore some of the more powerful MooseX:: modules available on CPAN.</p>

<p>Students are expected to bring a laptop, as you will be writing code during the class. You will also be provided with a tarball a week or so before the class is scheduled, which will contain a directory tree skeleton and test files.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>More on Catalyst Models</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2009/08/more-on-catalyst-models.html" />
    <id>tag:blog.urth.org,2009://2.109</id>

    <published>2009-08-11T15:58:35Z</published>
    <updated>2009-08-11T16:24:06Z</updated>

    <summary>Marcus Ramberg responded to my post on How I Use Catalyst, and I&apos;d like to respond to a few points he made. Marcus wrote: I disagree that $schema-&gt;resultset(&apos;Person&apos;) is a significant improvement on $c-&gt;model(&apos;DBIC::Person&apos;). Me too! I don&apos;t think the...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p><a href="http://marcus.nordaaker.com/2009/08/model-adaptors-for-catalyst/">Marcus Ramberg responded to my post</a> on <a href="http://blog.urth.org/2009/08/how-i-use-catalyst.html">How I Use Catalyst</a>, and I'd like to respond to a few points he made.</p>

<p>Marcus wrote:</p>

<blockquote>
  <p><em>I disagree that $schema->resultset('Person') is a significant improvement on $c->model('DBIC::Person').</em></p>
</blockquote>

<p>Me too! I don't think the former is a <em>significant</em> improvement over the latter. They are, after all, more or less the same. The one big problem is that the latter version uses a nonexisting <code>DBIC::Person</code> namespace. There are no <code>DBIC</code> classes anywhere in the app. I think the model version would be much better if it was just written as <code>$c-&gt;model('Person')</code>.</p>

<p>Marcus also points out that the model layer lets you configure multiple models and access them in a unified way. That is indeed nice. Unfortunately, that has the problem of tying yourself to Catalyst's config, which is problematic for reasons I already described. Similarly, the unified layer <em>only</em> exists inside Catalyst, which is really only accessible during a web request. So now we're stuck with recreating all of this if we need to access our models outside of a web request.</p>

<p>The long-term Catalyst roadmap includes the much-talked-about application/context split. Once this is done, presumably you will be able to access the application, which I take to mean config and models, outside of the context (of a web request). Once that is in place, I think many of my objections will go away. Unfortunately, for now I have to write my own application/context splitting code.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>She Said What?!</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2009/08/i-created-a-new-website.html" />
    <id>tag:blog.urth.org,2009://2.108</id>

    <published>2009-08-10T20:51:18Z</published>
    <updated>2009-08-10T20:55:19Z</updated>

    <summary>I created a new website as a fun little personal project, She Said What?! It was a fun experiment both in minimal web design, and also in minimal code. I can update it from the command line just by typing:...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="Personal" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p>I created a new website as a fun little personal project, <a href="http://shesaidwh.at/">She Said What?!</a></p>

<p>It was a fun experiment both in minimal web design, and also in minimal code. I can update it from the command line just by typing:</p>

<pre><code>ssw 'A quote goes here|and commentary goes here'
</code></pre>

<p>This adds a quote to the quote "database", which is just a directlory of timestamped flat files on my desktop. Then it regenerates the site as static HTML and pushes it to the live server.</p>

<p>The code is in <a href="http://hg.urth.org/hg/she-said-what">my mercurial repository</a> for anyone who might care.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>How I Use Catalyst</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2009/08/how-i-use-catalyst.html" />
    <id>tag:blog.urth.org,2009://2.106</id>

    <published>2009-08-02T14:50:50Z</published>
    <updated>2010-01-16T16:35:35Z</updated>

    <summary>Now that I&apos;ve written about My Way of the Webapp and what Catalyst really is, I&apos;ll explain what I don&apos;t like about Catalyst. I&apos;m not going to talk about things I know the Catalyst developers are aware of. In particular,...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p>Now that I've written about <a href="/2009/07/my-way-of-the-webapp.html">My Way of the Webapp</a> and <a href="/2009/07/what-is-catalyst-really.html">what Catalyst really is</a>, I'll explain what I don't like about Catalyst.</p>

<p>I'm <em>not</em> going to talk about things I know the Catalyst developers are aware of. In particular, the use of subroutine attributes for dispatching is horrible, and they know it. I'm excited to see <a href="http://search.cpan.org/CatalystX-Declare">CatalystX::Declare</a>, since something like that should be the future of Catalyst controllers. Another well-known misfeature is the rampant use of subclassing for plugins and the lack of well-defined APIs. <a href="http://blog.woobling.org/2009/07/reducing-scope.html">Yuval Kogman explained why this is so problematic</a> very nicely already.</p>

<p>Instead, I'm going to focus on what I consider "Catalyst Worst Practices", in particular misfeatures of Catalyst (and/or plugins) that many people use.</p>

<h2>Configuration File (Mis)Handling</h2>

<p><a href="http://search.cpan.org/dist/Catalyst-Plugin-ConfigLoader">Catalyst::Plugin::ConfigLoader</a> loads a config file and merges it into the application config set via <code>MyApp-&gt;config(...)</code>. "Wonderful", you say, "I'm sick of dealing with config files". Me too! Unfortunately, if you embrace this style of config handling you're setting yourself up for problems later.</p>

<p>It is <strong>absolutely crucial</strong> that your configuration file be available <strong>outside of a web environment</strong>. Yes, we're writing webapps, but any sufficiently complex web application <em>will</em> expand to include a cron job or job queue or some sort of asynchronous task. Usually this will involve sending email.</p>

<p>Unfortunately, ConfigLoader's config handling is very tightly integrated into its web components. First, it gets things conceptually wrong by combining all sorts of config into one massive hash. When you call <code>$c-&gt;config</code> you can find configuration items for ...</p>

<ul>
<li>Configuration info from your config file</li>
<li>Configuration info set in a call to <code>MyApp-&gt;config(...)</code></li>
<li>Configuration info for the current controller and its parents</li>
</ul>

<p>When you use ConfigLoader, your config file can contain both non-web things like database connections, as well configuration specific to your app, and configuration for plugins you use.</p>

<p>All of this gets jumbled together into one simplistic API. This API just gives you back the config info as a giant data structure, with no opportunity to add <em>logic</em> to the mix. Worse it's only available from inside an instantiated webapp via <code>$c-&gt;config</code>. This is wrong, wrong, wrong.</p>

<h3>How I Do It Instead</h3>

<p>I always write my own app-specific config module. This module will use a CPAN module for the actualy reading of files. I like to stick with a simple format, so <a href="http://search.cpan.org/dist/Config-INI">Config::INI</a> works nicely, but that's a small detail.</p>

<p>The configuration file contains the <em>most minimal</em> set of things it can in order to bootstrap the application. Typically, this will include database connection info and not much else. Maybe it also includes a hostname for the application, which may sometimes be necessary.</p>

<p>This module also includes <em>logic</em> for determining various application configuration values. Note that it does not allow (or require) the end user to configure these things. The fact that PluginLoader lets you configure <em>everything</em> from a configuration file is a nightmare. A configuration file is something that non-developers see, and should have a well-defined, <em>small</em> set of options.</p>

<p>I then use this module to generate configuration data for various parts of my application. In my webapp class, I use it to feed configuration data into Catalyst. That looks something like this:</p>

<pre><code>package R2;

use R2::Config;

use Moose;

my $Config;

BEGIN
{
    extends 'Catalyst';

    $Config = R2::Config-&gt;new();

    Catalyst-&gt;import( @{ $Config-&gt;catalyst_imports() } );
}

__PACKAGE__-&gt;config( name =&gt; 'R2',
                     %{ $Config-&gt;catalyst_config() },
                   );
</code></pre>

<p>Most of the configuration passed to Catalyst is not user-settable. For example, I don't want people installing an app to have control over how the Catalyst Session plugin is configured! This is part of the application internals, and users have no business messing with it.</p>

<p>This <code>R2::Config</code> module just works both inside Catalyst and outside of it. When I need application-wide config I simply need to write <code>R2::Config-&gt;new()-&gt;share_dir()</code> and it works. This means I can take advantage of my configuration in any context, not just inside a web request. This makes writing cron jobs and other non-web pieces trivially easy, although there is a bigger investment up front in designing the configuration module's API.</p>

<p>BTW, the "R2" example comes from <a href="http://hg.urth.org/hg/R2">a real app in progress</a>.</p>

<h2>The Maleficent "Model"</h2>

<p>Have you ever looked in a Catalyst class and seen something like <code>$c-&gt;model('DBIC::Person')-&gt;find(...)</code>? What is it doing? Well, not much, but it's just enough to make a mess.</p>

<p>A good example is the <a href="http://search.cpan.org/dist/MojoMojo">MojoMojo</a> source, which I've been hacking on recently. If you look at the source tree, you'll see that the model code lives under <code>MojoMojo::Schema::ResultSet::*</code> and <code>MojoMojo::Schema::Result::*</code>. The <code>MojoMojo::Schema</code> class ties this all together. In any sane world you'd be writing <code>$schema-&gt;resultset('Person')-&gt;find(...)</code>. But this is not a sane world.</p>

<p>You might argue that the Model bit is solving a problem, which is that we need to instantiate a schema object before we can get at the database. That <em>is</em> a problem that needs solving, but the model API adds nothing to this.</p>

<p>What is wrong with something like this?</p>

<pre><code>package MojoMojo;

has schema =&gt;
    ( is      =&gt; 'ro',
      lazy    =&gt; 1,
      default =&gt; sub { MojoMojo::Schema-&gt;connect() },
    );
</code></pre>

<p>Then later in our controllers we can write:</p>

<pre><code>$c-&gt;schema()-&gt;resultset('Person')-&gt;find(...);
</code></pre>

<p>If we've done our work on configuration handling as I described above, then <code>MojoMojo::Schema</code> knows just where to look for connection info. All that the model API adds is a useless layer of redirection (aka confusion) and a useless 'DBIC::' prefix to our resultset names.</p>

<p>(Nosy readers might point out that the R2 code does have a Model class. That was an experiment which must die.)</p>

<h2><code>$c-&gt;uri_for</code>? Not for Me!</h2>

<p>Here comes my ultimate heresy. I never use <code>$c-&gt;uri_for</code>. I <em>always</em> write application-specific logic for generating URIs. Once again, this comes back to being able to use my application outside of a web environment. For example, I may want to generate email from a cron job that includes application URIs. If I rely on <code>$c-&gt;uri_for</code> I would then need to duplicate its logic outside of Catalyst.</p>

<p>My current approach is to simply make generating URIs a responsibility of each object in the system. I don't love this, because it inflicts "web-ness" on my model, but I can rationalize this by considering the URI a persistent unique identifier. In the age of REST that actually makes sense.</p>

<p>This also lets me do things like install the application under a path prefix like "/r2". If the application supports adding an arbitrary prefix to all outgoing paths, this works nicely. I can strip the prefix before any controllers see it, so it requires very little code to support, just some configuration.</p>

<p>This approach is especially handy when an application is designed to be served from multiple hostnames. If you're doing this, you need to account for this in the above-mentioned emails. With R2, each Account (a group of Users) is associated with a Domain. A domain can have separate web and email hostnames, and those hostnames are always used when generating URIs for anything associated with the account.</p>

<p>If I used <code>$c-&gt;uri_for</code> I'd <em>still</em> need a way to go from a web hostname to an email hostname.</p>

<h2>Summary</h2>

<p>I encourage you to think twice before adopting every feature you see someone else use in a Catalyst app. Catalyst is great, but not everything about it supports long-term maintainable applications.</p>

<p>Some of its features make getting started with small apps really easy, but they will bite you in the ass as your app grows. With a little more work up front, you can build a cleaner app that won't require major hacks or rewriting later.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Moose Class in Minneapolis?</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2009/07/moose-class-in-minneapolis.html" />
    <id>tag:blog.urth.org,2009://2.105</id>

    <published>2009-07-27T23:20:26Z</published>
    <updated>2009-07-27T23:25:05Z</updated>

    <summary>I have this one day Moose class I&apos;ve developed. I was supposed to give it at YAPC, but I was sick and cancelled my trip. Here&apos;s the class summary I wrote for YAPC: This will be an interactive hands-on course...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p>I have this one day Moose class I've developed. I was supposed to give it at YAPC, but I was sick and cancelled my trip.</p>

<p>Here's the class summary I wrote for YAPC:</p>

<blockquote>
  <p>This will be an interactive hands-on course all about Moose. Moose is an OO system for Perl 5 that provides a simple declarative layer of "sugar" on top of a powerful, extensible meta-model.</p>
  
  <p>With Moose, simple classes can be created without writing any subroutines, and complex classes can be simplified. Moose's features include a powerful attribute declaration system, type constraints and coercions, method modifiers ("before", "after", and "around"), a role system (like mixins on steroids), and more. Moose also has a vibrant ecosystem of extensions as seen in the variety of MooseX:: modules on CPAN.</p>
  
  <p>This course will cover Moose's core features, dip a toe into the meta-model, and if there's time, explore some of the more powerful MooseX:: modules available on CPAN</p>
  
  <p>Students are expected to bring a laptop, as you will be writing code during the class. You will also be provided with a tarball a week or so before the class is scheduled, which will contain a directory tree skeleton and test files.</p>
</blockquote>

<p>The class ended up being taught by Shawn Moore, and I got a lot of good feedback about the class slides and exercises.</p>

<p>I'd really like to give the class myself, and I am trying to figure out if there's interest in the Twin Cities, MN area. I'd reserve a conference room at a hotel or on the UMN campus in Minneapolis or St Paul for the class, and I'm hoping to do this some time in August or September.</p>

<p>Normally, a one-day training session like this would run about $500 per person, but since this would be my first time actually giving the class, the rate would be a mere $120 per person.</p>

<p>In return, I want each attendee to commit to answering a short survey I'll give them after the class so I can get feedback on the class and my teaching. So there is a small price for the discount ;)</p>

<p>In order to make this happen, I'd need at least 5 people to sign up.</p>

<p>If you have questions, feel free to ask in a comment or <a href="mailto:autarch@urth.org">email me</a> or <a href="mailto:mpls-pm@pm.org">email the Minneapolis Perl Mongers list</a>.</p>

<p>If you're interested in attending, please let me know what days of the week are best. Would you prefer a weekday, Saturday, or Sunday? Or maybe it doesn't matter. Again, leave a comment or <a href="mailto:autarch@urth.org">email me</a>.</p>

<p>If there is enough interest, I'll schedule it and then announce it on this blog and Minneapolis Perl Mongers list.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>My Way of the Webapp</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2009/07/my-way-of-the-webapp.html" />
    <id>tag:blog.urth.org,2009://2.104</id>

    <published>2009-07-27T15:39:31Z</published>
    <updated>2009-07-27T17:35:38Z</updated>

    <summary>I&apos;ve been working on web applications for a long time, and over the years I&apos;ve developed a specific approach to structuring web application code. In the past few years, this has been strongly influenced by REST concepts. My approach leads...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p>I've been working on web applications for a long time, and over the years I've developed a specific approach to structuring web application code. In the past few years, this has been strongly influenced by <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">REST concepts</a>.</p>

<p>My approach leads me to make use of some existing concepts, like cookies and sessions, in an idiosyncratic way. Sometimes in discussions about web application I'll refer to these idiosyncrasies, but seen in isolation they may make no sense to anyone but me.</p>

<p>This entry will attempt to explain both my philosophical approach, and the practical consequences of that approach. This will <em>not</em> be a start-to-finish guide to building a web app (not even close).</p>

<h2>Each Action Does One Thing</h2>

<p>In this context, an action is a Catalyst action. In non-Catalyst speak, it's a method that handles the response for a request. With REST, a request is identified by both its URI <em>and</em> its method, so we distinguish between a GET and POST to the same URI.</p>

<p>So what is one thing? That one thing can be one or more related database changes, some other non-database task (sending an email), or generating output for the client (HTML or something else).</p>

<p>An importance consequence of this "one thing" rule is that an action can either change some state on the server <em>or</em> return data to the client. An action never does both (ignoring side effects like logging or stats tracking). For a browser, this means that all non-GET requests are followed by a redirect to a GET.</p>

<p>I cannot abide an application that receives a POST, updates the database, and then returns some HTML. Inevitably, this produces crufty code filled with conditionals.</p>

<p>The worst examples of this are applications that have a single URI that displays a form, and then on a successful form submission display a different page at the same URI. This is a huge violation of REST, and makes the code even more crufty with conditionals.</p>

<p>I think the main reason people like to combine POST/PUT/DELETE handling and HTML generation is to make it easier to give feedback to the user. If the submission is unsuccessful, we want to show the same form to the user with some error messages ("password is required"). When the submisson is successful we want to give them feedback about that ("your comment has been accepted and is pending review").</p>

<p>Of course, providing clear feedback to users is absolutely crucial in building a usable application, but we can have our RESTful, well-designed cake and eat it too.</p>

<h2>RESTful, Minimal Sessions</h2>

<p>Contrary to some of what you might read online, you can have sessions with REST. The key is that the URI must describe the whole item being requested, <em>including the session</em>. That means putting the session in the URI.</p>

<p>But putting sessions in the URI has all sorts of well-known problems. First, it makes for ugly URIs. Second, it means you have to carry that session URI throughout the application. Third, it makes session-jacking much easier.</p>

<p>The second problem is easy to address. Just don't carry the session URI throughout the application! A properly built web application does not need a session for every request. If you just use the session to carry a response to a POST/PUT/DELETE, you can limit the scope of the session. I only need to include a session in the URI as part of a redirect, so my HTML pages never include links with a session.</p>

<p>To that end, I keep my sessions extremely minimal. There are only three things I put in a session:</p>

<ol>
<li>Error messages - these can be either general messages like "you don't have access to edit comments" or specific to a form field like "this is not a valid email address".</li>
<li>Feedback messages - "your comment has been submitted for review"</li>
<li>Form data - when a form submission results in an error, you show the form to the user again, and always make sure to repopulate it with the data they submitted.</li>
</ol>

<p>All of this data shares the quality of being <em>transient</em>. It only needs to be used on a single URI. Once the user leaves the page in question, we no longer need the session.</p>

<p>This helps address the ugly URI problem. Most URIs just don't have a session, so we limit the scope of our ugliness.</p>

<p>This also helps address the session-jacking problem. Again, the data is transient, and is only needed on one page. Since I don't store authentication information in the session, you still need to authenticate to see the relevant page. This means that if the user gives the URI with a session to someone else, it doesn't matter.</p>

<p>In my applications, sessions expire after five minutes. If a user tries to go back to an old URI with a session, then the application simply redirects them to the session-less URI, which is always valid, because my applications have <a href="http://www.w3.org/Provider/Style/URI">Cool, RESTful URIs</a>, except for the session piece.</p>

<p>Taken together, this lets me have RESTful sessions with no security risk and minimal ugliness.</p>

<p>As a bonus, keeping sessions minimal helps force me to think clearly about application workflow, rather than just jamming tons of data into a session and using it all over the application.</p>

<h2>RESTful Cookie Authentication</h2>

<p>Much of the literature on REST suggests that in order to be properly RESTful, you need to use HTTP authentication. Of course, anyone who's ever worked on a real web application knows that HTTP authentication is a horrible, horrible thing to deal with. You have no control over the UI, it's impossible to logout except with insane hacks, and it makes for an overall horrible user experience.</p>

<p>Realistically, if your client is a web browser, you have to use a cookie for authentication. Many applications, however, use a <em>session</em> cookie. <em>Every</em> request involves a session lookup, and the user id is stored in the session. This is bad and wrong. First, it requires that we have a session on every page, which I don't like. Second, it egregiously violates RESTful principles by passing around an opaque token with unclear semantics.</p>

<p>For me, using an authentication-only cookie is close enough to REST. With an authentication cookie, we get an effect very similar to HTTP authentication. Every request includes the authentication information, and the server checks this on every request. There is no hidden state, and while this is still technically opaque, the opaque piece is as minimal as possible.</p>

<p>This still isn't really RESTful, but I just don't care. I'm all for doing things in an architecturally proper manner, but only if I can provide a great user experience too. Mostly, REST and a great experience are compatible, but when it comes to authentication, HTTP auth is simply not tenable.</p>

<p>However, I can at least minimize the degree to which I compromise, and using the cookie for authentication and authentication only is as minimal as I can get.</p>

<h2>Practical Consequences</h2>

<p>These approaches, taken together, have led me to write several Catalyst plugins and/or adopt others. First of all, I use <a href="http://search.cpan.org/dist/Catalyst-Action-REST">Catalyst::Action::REST</a>. I'm primarily interested in using it to let me dispatch GET, PUT, POST, and DELETE to different controller methods internally, and it does this very cleanly.</p>

<p>I also use my own <a href="http://search.cpan.org/dist/Catalyst-Request-REST-ForBrowsers">Catalyst::Request::REST::ForBrowsers</a> module. This lets me define all of my internal code in terms of the four HTTP methods mentioned above, but yet still work with browsers. Browsers have two problems. First, they don't accept arbitrary document types, so I can't return a well-defined document type of my choosing, I have to return HTML, and that HTML needs to include (by reference) information about styling (CSS) and client-side behavior (Javascript). This is fundamentally unlike a notional smart REST client. Second, browsers do not support PUT or DELETE, so I "tunnel" that through a POST.</p>

<p>I also use the <a href="http://search.cpan.org/dist/Catalyst-Plugin-Session">Catalyst Session plugin</a>, along with <a href="http://search.cpan.org/dist/Catalyst-Plugin-Session-State-URI">Catalyst::Plugin::Session::State::URI</a>. I make sure to configure the URI state plugin to only rewrite redirects, as mentioned earlier.</p>

<p>Yesterday, I released <a href="http://search.cpan.org/dist/Catalyst-Plugin-Session-AsObject">Catalyst::Plugin::Session::AsObject</a>. THis enforces session discipline by providing the session as an object, not a hash reference. Instead of writing <code>$c-&gt;session()-&gt;{errors}</code>, I write <code>$c-&gt;session_object()-&gt;errors()</code>. This makes it easy to limit what data can go in the session, and gives me a <em>much</em> nicer API for pulling data back out. Note that all the plugin does is let you configure the class name of the session object. You can provide your own class on a per-application basis, meaning you can use it for any session data you want, not just my three items.</p>

<p>For authentication, I use my own <a href="http://search.cpan.org/dist/Catalyst-Plugin-AuthenCookie">Catalyst::Plugin::AuthenCookie</a>. When I wrote this, the dominant <a href="http://search.cpan.org/dist/Catalyst-Plugin-Authentication">Catalyst Authentication plugin</a> required that the user authentication be stored in a session. Since I did not want a session on every request, I ended up writing my own plugin. Since that time, the original Authentication plugin has made use of the session has optional, but I still find it dauntingly complex for common use, so I'll stick with my own plugin.</p>

<p>So that's a slice of my approach to web applications. Hopefully this was interesting, and less confusing than hearing about it piecemeal. It may also help explain why I've written some of my modules, in case anyone was wondering "what use is X".</p>
]]>
        

    </content>
</entry>

<entry>
    <title>I Am the Master of Wheels</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2009/07/i-am-the-master-of-wheels.html" />
    <id>tag:blog.urth.org,2009://2.103</id>

    <published>2009-07-26T02:54:45Z</published>
    <updated>2009-07-26T16:59:20Z</updated>

    <summary>It occurred to me today that if you look at my history as a CPAN author, you&apos;ll see that I&apos;ve either written or heavily participated in every popular target of re-invention on CPAN! I started off by writing an ORM,...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p>It occurred to me today that if you look at my history as a CPAN author, you'll see that I've either written or heavily participated in every popular target of re-invention on CPAN!</p>

<p>I started off by writing an ORM, <a href="http://search.cpan.org/dist/Alzabo">Alzabo</a>. Back when I released it, this was one of the very first ORMs for Perl. Amusingly, I re-invented the whole ORM concept pretty much independently. I don't think I even heard the term until after Alzabo was released.</p>

<p>(<a href="http://search.cpan.org/dist/Class-DBI">Class::DBI</a> was also released around the same time, and became much more popular.)</p>

<p>Of course, if you do enough database programming in an OO language, an ORM is an obvious concept to "invent", and that probably explains why there's so damn many of them. People "invent" them before they realize that there are dozens already out there.</p>

<p>I've also worked on a templating system, <a href="http://www.masonhq.com/">Mason</a>. In fact, before that, I wrote a mini-templating system at Digital River, where I worked with Ken Williams. Fortunately, Ken pointed me at Mason before I could get too far into my own, which was a good thing.</p>

<p>Mason is <em>also</em> a (primitive) webapp framework, so I've worked on one of those too, as well as providing an odd patch or two to Catalyst and various Catalyst plugins.</p>

<p>Then there's the <a href="http://datetime.perl.org">Perl DateTime project</a>, which was an explicit and clearly thought out wheel reinvention exercise. The existing wheels were all kind of broken, and you couldn't easily put any two wheels on the same car, so we came up with a plan for a whole set of interchangeable wheels and assorted other parts.</p>

<p>Nowadays I spend a lot of time on <a href="http://moose.perl.org">Moose</a>, which is one of the most recent (and by far the best) in a long series of "make Perl 5 OO better" modules.</p>

<p>To top off my wheel-ish history, I have a <a href="http://search.cpan.org/dist/Fey-ORM"><em>new</em> ORM, Fey::ORM</a>, meaning I am the creator of both one of the oldest and one of the newest ORMs on CPAN.</p>

<p>Truly, I am the master of wheels, both re-invention and polishing those already in existence.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Not going to OSCON either</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2009/07/not-going-to-oscon-either.html" />
    <id>tag:blog.urth.org,2009://2.100</id>

    <published>2009-07-14T16:04:49Z</published>
    <updated>2009-07-14T16:06:44Z</updated>

    <summary>Well, I thought I was getting better, but I was wrong. Last week my infection seems to have had a resurgence, and I&apos;m not feeling well enough to travel. Yuval Kogman has offered to teach the Moose tutorial at OSCON,...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p>Well, I thought I was getting better, but I was wrong. Last week my infection seems to have had a resurgence, and I'm not feeling well enough to travel.</p>

<p>Yuval Kogman has offered to teach the Moose tutorial at OSCON, so that will still go on, assuming O'Reilly agrees to the switch.</p>

<p>I'm still hoping to go to Italy in October. If I'm not recovered by then, I'm just going to have to get a robot body, because this meat sack is not working out so well.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>What is Catalyst, Really?</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2009/07/what-is-catalyst-really.html" />
    <id>tag:blog.urth.org,2009://2.96</id>

    <published>2009-07-02T16:54:32Z</published>
    <updated>2009-07-26T17:01:07Z</updated>

    <summary>A recent thread on the Mason users list reminded me of the problems I had grokking Catalyst when I first looked at it. Raymond Wan wrote &quot;I&apos;m skimming over the MVC part and as my system doesn&apos;t use an SQL...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p>A <a href="http://www.nabble.com/new-Mason-tutorial-to24256045.html">recent thread on the Mason users list</a> reminded me of the problems I had grokking Catalyst when I first looked at it. Raymond Wan wrote "I'm skimming over the MVC part and as my system doesn't use an SQL database, I'm wondering if Catalyst is overkill??"</p>

<p>Those of us who know Catalyst know that this question is based on some wrong assumptions, but it's easy to see why Raymond has those assumptions. Look at the <a href="http://search.cpan.org/~hkclark/Catalyst-Manual-5.8000/lib/Catalyst/Manual/Tutorial/01_Intro.pod">Catalyst tutorial</a>. In the very first chapter, it's already talking about databases and <a href="http://search.cpan.org/dist/DBIx-Class">DBIx::Class</a>.</p>

<p>It's easy to look at this and assume that Catalyst is somehow tightly bound to DBIx::Class or SQL databases.</p>

<p>The problem is that the tutorial docs really need to serve two different audiences, though both audiences are Catalyst newbies.</p>

<p>On the one hand, you have people with relatively little web app experience. Presumably, they know some Perl, and they do a web search for "perl web application framework". Eventually, they'll get to Catalyst and start reading about it. For those people, being given a set of standards and a full walk through of Model and View (in addition to Controller) is very valuable. It gives them all the tools they need to get started on simple web apps without having to make too many choices.</p>

<p>The other audience is people who have some real web app development experience with something more primitive than Catalyst. These could be people coming from a Mason-based site without any real controllers, or people who used something like Apache::Template with mod_perl, or maybe they wrote their own controllers "by hand" using the mod_perl API.</p>

<p>Many of those folks will already have some experience with models. To refer back to Raymond, presumably his system already has some sort of model code, it just doesn't use a SQL DBMS. Those people will look at the existing Catalyst tutorial and get confused. Isn't Catalyst flexible? Then why does it look like RoR, with all my tool choices made for me?</p>

<p>It took me a while to realize that Catalyst, at its core, is smaller than you might think, and you can use just the pieces you like.</p>

<p>The very core of Catalyst is its dispatching system. Given a URI, it selects a piece of code to run. Its dispatcher is very powerful (Chained methods are great!), and with plugins like <a href="http://search.cpan.org/dist/Catalyst-Action-REST">Catalyst::Action::REST</a>, it's even better.</p>

<p>Along with the dispatching system, Catalyst also provides an abstraction over the typical web app request/response cycle. The Request makes it easy to look at incoming query arguments, POST data, file uploads, and headers. The Response lets you set headers and return output to the client, whether that be HTML or a downloadable file.</p>

<p>Catalyst also includes engines (think "environment adapters") for a number of common web application environments, including vanilla CGI, mod_perl, FastCGI, and more. These engines make sure that the Request/Response API works exactly the same in any environment where Catalyst can be deployed.</p>

<p>This is a huge win, since you can write your app without worrying about the deployment environment. If you're writing an app for public distribution, it gives the installing users a choice of how to deploy.</p>

<p>These core pieces are really the only parts of Catalyst you have to use when you use Catalyst. If you don't want dispatch and a request/response API, you don't want Catalyst.</p>

<p>Catalyst (really <a href="http://search.cpan.org/dist/Catalyst-Devel">Catalyst-Devel</a>) also includes a fantastic single-process development server. This server can be started straight from an application's checkout directory with one command. Even better, this dev server can be told to monitor all relevant files and restart itself when any of them change. Note that this is a proper restart, which avoids all the myriad problems that afflict Apache::Reload and its ilk, which attempt to reload modules in the same Perl interpreter.</p>

<p>Just these things - controllers, a request/response abstraction, deployment agnosticism, and a great dev environment - are enough to make Catalyst a great choice. Ignore everything else it does and you'll still have improved your development process and improved your code.</p>

<p>Catalyst also does some other things ...</p>

<p>It has a component system which has allowed people to release a whole host of useful plugins. If you look on CPAN, you'll find things like <a href="http://search.cpan.org/dist/Catalyst-Plugin-Session">sessions</a>, <a href="http://search.cpan.org/dist/Catalyst-Plugin-Authentication">powerful authentication</a>, <a href="http://search.cpan.org/dist/Catalyst-Plugin-AuthenCookie">dumb authentication</a>, <a href="http://search.cpan.org/dist/Catalyst-Plugin-I18N">I18N</a>, and much more. If a plugin does what you need, it'll save you a lot of development time.</p>

<p>Note that the old "Catalyst::Plugin" system is in the process of being deprecated, but the concept of pluggable components is still core to what Catalyst is. All that's changed is the way pluggability works.</p>

<p>Catalyst lets you have multiple views. While many apps will just output HTML via a templating system, this flexibility is great for RESTful apps that may want to output XML, JSON, and still fall back to HTML for browsers (see my <a href="http://search.cpan.org/dist/Catalyst-Request-REST-ForBrowsers">REST-ForBrowsers</a> for some help with that).</p>

<p>Catalyst also has configuration file handling built-in. Personally, I avoid it, because it only works within the context of the whole "Catalyst environment". That means it's awkward at best to load the configuration outside of the web environment. I always make sure that application wide setting are available for things like cron jobs. This falls into a category of Catalyst features which are not best practices, but are probably useful for people writing their first web app.</p>

<p>Catalyst gives you hooks for models. Again, this is something I never use, but it's another "useful for web app n00bs" feature.</p>

<p>There's probably many other things I've left out. The point is that Catalyst provides a very powerful set of core web app tools, and that core is actually small.</p>

<p>Relative to a "my way or the highway" type framework (RoR and Jifty, I'm looking at you), it's easy to port an existing application to Catalyst. In fact, using <a href="http://search.cpan.org/dist/Catalyst-Controller-WrapCGI">Catalyst::Controller::WrapCGI</a>, you can wrap an existing CGI application with Catalyst, and then convert slowly over to "native" controllers.</p>

<p>And most importantly, you can move to Catalyst without touching your model at all! Since many applications have the bulk of their code in the models (at least, they do if you're doing it right), this is a huge win.</p>

<p>Next step is to turn some of this rambling into doc patches. I think a section of the Catalyst tutorial aimed at folks coming from an "old school" web app background would be great, and would really help people like Raymond (and would've helped me a few years back).</p>
]]>
        

    </content>
</entry>

<entry>
    <title>I won&apos;t be at YAPC 10</title>
    <link rel="alternate" type="text/html" href="http://blog.urth.org/2009/06/i-wont-be-at-yapc-10.html" />
    <id>tag:blog.urth.org,2009://2.91</id>

    <published>2009-06-18T00:27:28Z</published>
    <updated>2009-06-18T00:33:35Z</updated>

    <summary>So a few weeks ago I got an infection that&apos;s quite painful to have. The infection is gone but the pain lingers on, and according to my doctor can linger for months. I realized today that I am still exhausted...</summary>
    <author>
        <name>Dave Rolsky</name>
        
    </author>
    
        <category term="Programming" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.urth.org/">
        <![CDATA[<p>So a few weeks ago I got an infection that's quite painful to have. The infection is gone but the pain lingers on, and according to my doctor can linger for months.</p>

<p>I realized today that I am still exhausted from being sick, as well as being involved in the planning of three major events over the last six months or so - Frozen Perl, my AR group's fundraising banquet, and our <a href="http://www.tlov.org/tlov2009/">conference this past weekend</a>.</p>

<p>To compound things, because of the pain I'm in, I can't sleep comfortably lying down, so I've been sleeping a comfy chair in my living room for a few weeks. I was really dreading trying to sleep in a hotel, since they wouldn't have comfy chairs.</p>

<p>So I decided to cancel the trip, even though I really didn't want to. My wife helped me realize that I <em>needed</em> to.</p>

<p>Fortunately, Shawn Moore, Jon Rockway, and Stevan Little are helping make sure the Moose class will still happen. Some of the content will be slightly different, but I think it will still be quite good. I've already written a little more than half the material, and I will write some more over the next few days. Shawn and Jon also have existing talks that cover topics I wanted to cover in the class, so they will include those talks.</p>

<p>Overall, I think the class will work out, and I'm really thankful to Shawn, Jon, and Stevan for agreeing to jump in at the last minute. Since the class is on Sunday, I'm sure people have arranged their travel schedules specifically to be there, and I'd really be sad if there was no class for them to attend.</p>

<p>I'm still planning to be at OSCON (I <em>better</em> be recovered enough by then), and I'm still considering YAPC::Asia.</p>

<p>I hope everyone has a good time in Pittsburgh.</p>
]]>
        

    </content>
</entry>

</feed>
