<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Perlblogs</title>
	<atom:link href="http://perlblogs.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://perlblogs.com</link>
	<description>Posts from selected Perl bloggers</description>
	<lastBuildDate>Fri, 18 May 2012 19:03:44 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>Programming Breaks Things</title>
		<link>http://www.modernperlbooks.com/mt/2012/05/programming-breaks-things.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/05/programming-breaks-things.html#comments</comments>
		<pubDate>Fri, 18 May 2012 16:38:38 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[novices]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[softwaredevelopment]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=b6345d9b3c23b4c3ea0c9e62c41cc9ce</guid>
		<description><![CDATA[Computer scientist Edsger Dijkstra famously said &#34;It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration.&#34; I disagree, in principle and...]]></description>
			<content:encoded><![CDATA[
        <p>Computer scientist Edsger Dijkstra famously said "It is practically
impossible to teach good programming to students that have had a prior exposure
to BASIC: as potential programmers they are mentally mutilated beyond hope of
regeneration."</p>

<p>I disagree, in principle and in practice. (I disagree so strongly that I
work on <a href="http://clubcompy.com/">a project to teach programming to
children</a>.)</p>

<p>I believe it's almost impossible to teach programming to someone who hasn't
experienced what we USians call "Geometry". That's mathematics: not the
specific behavior of triangles and angles and their relationships, but the hard
work and creativity and even beauty of following a set of logical rules to a
desirable conclusion. People who can do that can program effectively. People
who can't do that will struggle.</p>

<p>Before you can solve a big problem, you have to break it.</p>

<p>One of my work projects is a document categorization system. I've written
before that it uses a pipeline processing model, where a document moves through
the pipeline in various named stages. One stage might be "NEW", while another
might be "EXTRACT METADATA". As the system runs, documents make their way
through the pipeline in various stages and eventually enter a search index and
an archive intended for users.</p>

<p>Documents come from various places, and it's possible for identical (or
near-dentical) documents to enter the system at various times. I've long had an
exact title match filter as a first approach to remove duplicates, but it's
never filtered out enough duplicates. (Some documents are essentially press
releases barely edited and republished by multiple news organizations. These
documents are almost never interesting and are frustrating in their sameness
within the archive, but in the system they go regardless.)</p>

<p>We've talked about several approaches to finding duplicate and
near-duplicate articles, with everything from heuristics to identify title
similarity to maintaining multiple latent semantic indexes for each unique
category of documents. I dragged my feet on the latter because documents expire
after 90 days, and managing an n-dimensional corpus search space where one of
those dimensions is also <em>time</em> was more work than I wanted.</p>

<p>Wednesday I realized that a na&iuml;ve approach could give really good
results while being easy to code and, more importantly, very quick to run. I
coded and deployed it yesterday, and tuned it and deployed an improved version
as I was writing this very paragraph. I added a new processing stage which
makes a word histogram for every new document entering the system and compares
those histograms to existing articles. If they're similar enough, the new
article gets invalidated before it enters the search index or undergoes any
further processing.</p>

<p>It's silly, but it works. It's 108 lines of code, per sloccount.</p>

<p>I realized something while writing it: <em>programming is breaking
things</em>.</p>

<p>Long years of programming experience have taught me that most problems are
too big. Most functions are too long. Most methods are too long. Most entities
in the system do too much.</p>

<p>If you read much novice code, you see long functions (if you see functions
at all) with deeply nested conditionals and mutable state mutating all over the
place, because a variable at the top of the program gets used all throughout
the entire program. You see a mess, and you see a maintenance burden, and you
see someone flailing to control something that's grown way out of hand.</p>

<p>(You see this in part because people trying to learn <em>how</em> to program
are also learning the syntax and semantics of a programming language, and until
you know the vocabulary rules, you're going to have trouble understanding
nuance of meaning and metaphor and idioms.)</p>

<p>I had no trouble writing this code in in the small because I know the tools
Perl provides for me: hashes and arrays and methods.</p>

<p>I had little trouble writing this code, because I understand the pattern of
fetching a document at a time from an iterator and processing it to get a
histogram and putting that histogram in an array for later processing.</p>

<p>I had an easy time testing this code because I know how to write testable
code: each of my methods has a well-defined input and a well-defined output and
I can test only at those boundaries to see what happens.</p>

<p>Even though you don't know the details of this system, if you're a decent
programmer, you can probably write an outline of how the code works just from
how I've described it already:</p>

<ul>

<li>Get a collection of all active extant documents</li>

<li>Iterate over them</li>

<li>Fetch a histogram of each</li>

<li>Get a collection of all new documents</li>

<li>Iterate over them</li>

<li>Fetch a histogram of each</li>

<li>Compare each to every document in the histogram array</li>

<li>Invalidate the document if it matches any histogram too closely</li>

<li>Add the document's histogram to the array</li>

</ul>

<p>You can probably guess the names of my methods. If you're not exactly right, you're close.</p>

<p><em>This</em> is the discipline and experience that sets a good programmer
apart from a novice. Sure, a novice (or an undisciplined programmer) could
write twice as much code to do the same thing and get it working. Maybe he or
she could write four times as much code. (I don't pretend that my factoring of
this code is the rightest way to do it, but I do know that it passes multiple
tests.)</p>

<p>That's my writing in the small. My writing in the large is even more
interesting.</p>

<p>Each stage in the pipeline is its own self-contained class. I call them app
classes. Every app class conforms to an interface and gets run by a runner.
Every app connects to a defined logger and performs its own registration and
reporting.</p>

<p>Every app has a method to fetch its basic resultset (every app is part of a
processing pipeline; obviously it's going to iterate over documents in a
certain state). Every app has method hooks to fire before this iteration and
after it. Every app has a <code>process()</code> method which performs the
iteration.</p>

<p>I've extracted and formalized the thirteen app classes over the past several
months. They started as a series of individual scripts. Then they had a common
base class. Now they share code with roles, take configuration out of a common
configuration file, and register themselves when loaded as plugins. They can
run separately (great for testing) or all together (as is normal).</p>

<p>I knew from the start that I was <a
href="http://www.modernperlbooks.com/mt/2012/05/write-the-wrong-code-first.html">writing
suboptimal code I'd eventually have to change</a>, but that's because I didn't
know enough about the problem yet. I'd discover that as the project went on.
I'd gain more insight as I saw what kinds of documents we'd have to handle (and
how very strange some of them are compared to what we expected).</p>

<p>The original concept of refactoring always reminds me of math. We rearrange
things to make them clearer, to prepare us to do other work, or harder work, or
at least further work. It's not change for change's sake, and it's not change
to add or remove or modify behavior. It's nothing more or less than changing
the design of things without changing their behavior.</p>

<p>It's the same skill, from writing functions of the right name and size to
putting modules in the right places with the right contents. It's about
breaking big things into smaller things. It's about breaking things into the
right things.</p>

<p>(Dijkstra <em>is right</em> that BASIC affords few abstraction possibilities
to break programs into effective and distinct components, but for novice
programmers the experience of turning what seems like a simple task into the
steps required to accomplish it is an important experience. That's also one reason why <a href="http://modernperlbooks.com/books/modern_perl/">Modern Perl: The Book</a> uses small test programs to demonstrate language features: working in small steps is too important to ignore.)</p>
        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/05/18/programming-breaks-things/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Time Will Tell</title>
		<link>http://www.modernperlbooks.com/mt/2012/05/time-will-tell.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/05/time-will-tell.html#comments</comments>
		<pubDate>Wed, 16 May 2012 22:28:41 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[refactoring]]></category>
		<category><![CDATA[softwaredevelopment]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=9e430894d87672b1231f0173c768910a</guid>
		<description><![CDATA[The May 2012 Dr. Dobb's interview with Ward Cunningham has an interesting quote about Ward's notion of technical debt: I was really devoted to finding great code, especially when objects were new. Objects gave us an extra dimension beyond functional...]]></description>
			<content:encoded><![CDATA[
        <p>The <a href="http://www.drdobbs.com/architecture-and-design/240000393">May 2012 Dr. Dobb's interview with Ward Cunningham</a> has an interesting quote about Ward's notion of technical debt:</p>

<blockquote><em>I was really devoted to finding great code, especially when objects were new. Objects gave us an extra dimension beyond functional decomposition. And the question was, "Are these the right objects or not?" And the answer was, "Time will tell."</em></blockquote>

<p>I work off and on with a handful of great programmers in the Portland area.
Several years ago, <a href="http://jamesshore.com/">James Shore</a> and <a
href="http://woldrich.com/">Dave Woldrich</a> created <a
href="http://cardmeeting.com/">CardMeeting</a>, an agile remote collaboration
tool. Jim and Dave are both very good programmers. For this project, they
decided to forgo their usual test-driven development and just write code so as
to deliver a working prototype on a vry strict deadline.</p>

<p>Jim took to calling that experience "leveraged technical debt". My estimate
(not having read the code, but having tested a lot of code written without
testing in mind) is that it takes at least as long to write tests for untested
code as it took to write the code <em>and much longer the more time has passed
between writing the code and writing the tests</em>.</p>

<p>Jim, Dave, and I have all worked on small, software-driven businesses doing
things we've never seen anyone else do before. We've all had to deal with the
risk of building lots of code that may or may not solve the problems of real
customers with real money. When I say <a
href="http://www.modernperlbooks.com/mt/2012/05/write-the-wrong-code-first.html">write
the wrong code first</a>, I don't mean "deliberately do things you know won't
work" or "paint yourself into a corner" or even "use the fact you don't know
everything you're doing as an excuse to play with completely new technologies
you don't know how to use". (Not that the latter is a bad thing, but if you
decide to do that, do so only after you've considered the risks and the
rewards.)</p>

<p>Last night, we had a short conversation with <a
href="http://johnwilger.com/">John Wilger</a>, another PDXer. He works with a
successful and relatively young startup with a huge software component. I don't
want to put words in his mouth, but it sounds like their software is,
colloquially, a mess. Their developer team is trying to get to the point of
slapping hands whenever someone needs to make a change and starts by copying
and pasting code.</p>

<p>Four years after founding (and two years after discovering its cash cow
business), the company was worth at least $3 billion.</p>

<p>It's irresponsible to derive meaningful statistics from a single data point,
but we can say this: the technical debt of their codebase didn't entirely
prevent the company from achieving its current measure of success. (You can
also say that the liberal application of candy-flavored magical unicorn
shavings of Ruby and Rails didn't prevent people from making an unholy
mess.)</p>

<p><em>Time will tell</em> if changing the development culture and refactoring
the code and paying down all of the technical debt will help the company adapt
and take advantages of new opportunities.</p>

<p><em>Time will tell</em> if the codebase collapses under its own weight.</p>

<p><em>Time will tell</em> if a competitor (and several exist!) will prove more
agile and nimble because it has much better flexibility thanks, in part, to
better code.</p>

<p>The whole situation reminds me of <a
href="https://www.facebook.com/notes/facebook-engineering/the-hiphop-virtual-machine/10150415177928920">Facebook's
HipHop virtual machine</a>, where it's apparently cheaper and easier and
faster and less risky to hire lots of developers to create and maintain a
compatibility layer for the existing code than to rewrite existing code in a
better language, or in a better fashion, or to improve it meaningfully.</p>

<p>I'm not suggesting that the only way to build a big business from nothing is
to write bad code. I'm not suggesting that scaling to billions in revenue is
the goal of all software-driven businesses. I'm not suggesting that you have to
choose between test-driven development and business success.</p>

<p>In an ideal world, I can write the right software the first time. I can have
sufficient test coverage to have complete confidence in the behavior of the
code. I can deliver a feature which gets me paying customers in an afternoon
without having to rewrite other parts of the code or taking shortcuts I know
that I'll have to clean up when I get a spare weekend afternoon.</p>

<p>For a profession where some of us call ourselves "engineers", we certainly
spend a lot of time discussing practical concerns as if the risks and rewards
and limitations of the real world did not apply. (I wonder if the
academic/practical divide between computer science and software development has
some relationship to this.)</p>

<p>In the real world, I have to remind myself every day when I'm working on
proof of concept code that proving my concept workable is more important than
solidifying my code into well-tested and well-designed software and when I'm
working on code I intend to keep that doing things as right as possible now
will help me modify it to get it more right in the future.</p>

<p>None of this guarantees success. All of this benefits from the hard-won
experiences I have from doing things the wrong way&mdash;and occasionally
getting it very right. (In the real world, I spent part of the day finding and
deploying a shim to turn SVG into VML for Internet Explorer 8 and earlier.)</p>

<p>Maybe Jim and Dave could have thrown out a couple of features and spent more
time writing tests for the most valuable parts of their application. Maybe I'm
wasting my time optimizing SQL queries for a search feature no one will ever
use. Maybe John's company waited too long to untangle the admin and the user
sides of their application.</p>

<p>If we're honest with ourselves, the best answer we can give is that time
will tell. May we pay attention when it does.</p>
        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/05/17/time-will-tell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Perlbuzz news roundup for 2012-05-14</title>
		<link>http://feedproxy.google.com/~r/PerlBuzz/~3/9yfCnPNae8Q/perlbuzz-news-roundup-for-2012-05-14.html</link>
		<comments>http://feedproxy.google.com/~r/PerlBuzz/~3/9yfCnPNae8Q/perlbuzz-news-roundup-for-2012-05-14.html#comments</comments>
		<pubDate>Mon, 14 May 2012 19:20:11 +0000</pubDate>
		<dc:creator>Andy Lester</dc:creator>
				<category><![CDATA[conferences]]></category>
		<category><![CDATA[cpan]]></category>
		<category><![CDATA[Perl 5]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=bac1182143c5db6e52490336c3f09591</guid>
		<description><![CDATA[These links are collected from the Perlbuzz Twitter feed. If you have suggestions for news bits, please mail me at andy@perlbuzz.com. YAPC::NA will be livestreamed in real-time for free (blog.yapcna.org) Introduction to how to do Perl one-liners (catonmat.net) NYTProf,...]]></description>
			<content:encoded><![CDATA[
        <p>
These links are collected from the
<a href="http://twitter.com/perlbuzz">Perlbuzz Twitter feed</a>.
If you have suggestions for news bits, please mail me at
<a href="mailto:andy@perlbuzz.com">andy@perlbuzz.com</a>.
</p>

<ul>

<li>YAPC::NA will be livestreamed in real-time for free (<a href="http://blog.yapcna.org/post/22588737837/yapc-na-will-be-televised">blog.yapcna.org</a>)</li>
<li>Introduction to how to do Perl one-liners (<a href="http://www.catonmat.net/blog/introduction-to-perl-one-liners/">catonmat.net</a>)</li>
<li>NYTProf, File IO, and an Optimization Gone Awry (<a href="http://www.modernperlbooks.com/mt/2012/05/nytprof-file-io-and-an-optimization-gone-awry.html">modernperlbooks.com</a>)</li>
<li>Reddit API for Perl (<a href="http://blogs.perl.org/users/jeff_ober/2012/05/reddit-api-for-perl.html">blogs.perl.org</a>)</li>
<li>Lots of Perl authors at YAPC::NA this year (<a href="http://blog.yapcna.org/post/22717040291/lots-of-perl-authors">blog.yapcna.org</a>)</li>
<li>Review of "Programming Perl, 4th ed." (<a href="http://i-programmer.info/bookreviews/116-perl/4189-programming-perl.html">i-programmer.info</a>)</li>
<li>Don't use Cache::Memcached for UTF8 strings (<a href="http://domm.plix.at/perl/2012_05_10_dont_use_cache_memcached_for_utf8_strings.html">domm.plix.at</a>)</li>
<li>PerlGSL, interfaces to the GNU Scientific Library (<a href="http://blogs.perl.org/users/joel_berger/2012/05/announcing-perlgsl---a-collection-of-perlish-interfaces-to-the-gnu-scientific-library.html">blogs.perl.org</a>)</li>
<li>Learning Perl with testing (<a href="http://nbezzala.blogspot.com/2012/04/learning-perl-with-testing.html">nbezzala.blogspot.com</a>)</li>
<li>Separating presentation and content in TT (<a href="http://www.modernperlbooks.com/mt/2012/05/separating-presentation-from-content-in-templates.html">modernperlbooks.com</a>)</li>
</ul>

        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=9yfCnPNae8Q:-WfIU6fGL0o:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PerlBuzz?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=9yfCnPNae8Q:-WfIU6fGL0o:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PerlBuzz?i=9yfCnPNae8Q:-WfIU6fGL0o:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=9yfCnPNae8Q:-WfIU6fGL0o:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PerlBuzz?i=9yfCnPNae8Q:-WfIU6fGL0o:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=9yfCnPNae8Q:-WfIU6fGL0o:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PerlBuzz?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/PerlBuzz/~4/9yfCnPNae8Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/05/14/perlbuzz-news-roundup-for-2012-05-14/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Separating Presentation from Content in Templates</title>
		<link>http://www.modernperlbooks.com/mt/2012/05/separating-presentation-from-content-in-templates.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/05/separating-presentation-from-content-in-templates.html#comments</comments>
		<pubDate>Mon, 14 May 2012 18:47:11 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[modernperl]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[templating]]></category>
		<category><![CDATA[webprogramming]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=4f5d73f0d2b0265d5fdbbecd96a82b97</guid>
		<description><![CDATA[A couple of comments on Simple Attribute-Based Template Exporting have asked for an example. I'll show off more of this code in my YAPC::NA 2012 and Open Source Bridge 2012 talk about how to write the wrong code (along with...]]></description>
			<content:encoded><![CDATA[
        <p>A couple of comments on <a
href="http://www.modernperlbooks.com/mt/2012/05/simple-attribute-based-template-exporting.html">Simple
Attribute-Based Template Exporting</a> have asked for an example. I'll show off
more of this code in my <a href="http://act.yapcna.org/2012/talk/50">YAPC::NA
2012</a> and <a href="http://opensourcebridge.org/proposals/796">Open Source
Bridge 2012</a> talk about how to write the wrong code (along with a handful of
other techniques).</p>

<p>(I assume some knowledge of <a
href="http://search.cpan.org/perldoc?Template">Template Toolkit</a> (besides
far too many books about finance, accounting, and investing, the Template
Toolkit book is always within reach these days); I've set up a wrapper template
which provides the standard look and feel of my application and I
include/process other templates liberally. If you understand that much, you'll
be able to follow along.)</p>

<p>One of the interesting templates in the system displays a list of chapters
of a book in progress. A cron job rebuilds a static page from this template
once a day. The template looks something much like:</p>

<pre><code>[% USE Bootstrap -%]
[%- canonical_url = 'http://sitename.example.com/book/' _ link -%]

[%- add_og_properties({
    'fb:admins'      =&gt; '436500086365356',
    'og:title'       =&gt; title _ ' | sitename.example.com',
    'og:type'        =&gt; 'article',
    'og:image'       =&gt; 'http://static.sitename.example.com/images/logo.png',
    'og:url'         =&gt; canonical_url,
    'og:description' =&gt; text.chunk(300).0,
    'og:site_name'   =&gt; 'Sitename: site tag line',
   })
-%]
[%- add_meta(
    'pagetitle'     =&gt; title _ ' | sitename.example.com',
    'feed_url'      =&gt; 'http://static.sitename.example.com/book/atom.xml'
    'canonical_url' =&gt; canonical_url
) -%]

[% article_text = BLOCK -%]
&lt;article&gt;
&lt;h2&gt;[% title | html %]&lt;/h2&gt;
&lt;p&gt;Published: &lt;time datetime="[% date %]"&gt;[% nice_date %]&lt;/time&gt;&lt;/p&gt;
[% text %]
&lt;/article&gt;

&lt;ul class="pager"&gt;
[%- IF prev -%]
    &lt;li&gt;&lt;a href="[% prev.link %].html"&gt;&larr; [% prev.title | html %]&lt;/a&gt;&lt;/li&gt;
[%- END -%]
    &lt;li&gt;&lt;a href="/onehourinvestor"&gt;index&lt;/a&gt;&lt;/li&gt;
[%- IF next -%]
    &lt;li&gt;&lt;a href="[% next.link %].html"&gt;[% next.title | html %] &rarr;&lt;/a&gt;&lt;/li&gt;
[%- END -%]
&lt;/ul&gt;

[% INCLUDE 'components/social_links.tt', title =&gt; title %]
[%- END -%]

<strong>[%- row(
    maincontent( article_text ),
    sidebar(
        sideblock( process( 'components/cached/book_latest_chapters.tt' ) ),
        sideblock( process( 'components/cached/book_drafts.tt'          ) )
    )
) -%]</strong></code></pre>

<p>The emboldened lines are most important; they put all of the
<em>content</em> produced or assembled by this template in the HTML structure
the site needs. That is to say, everything on the site needs to fit into
something I call a <code>row</code>. A <code>row</code> can contain multiple
elements, such as <code>maincontent</code> and a <code>sidebar</code>, or
<code>fullcontent</code> by itself with no <code>sidebar</code>. A
<code>sidebar</code> can contain multiple <code>sideblock</code>s.</p>

<p>(You can ignore the other functions; they put metadata in the right places
to pass to wrapper templates.)</p>

<p>Within my template plugin (called <code>Bootstrap</code>), each of these
elements is a simple Perl function which takes one or more arguments and
interpolates it into some HTML:</p>

<pre><code>sub row :Export
{
    return &lt;&lt;END_HTML;
&lt;div class="row"&gt;
    @_
&lt;/div&gt;
END_HTML
}

sub sidebar :Export
{
    return &lt;&lt;END_HTML;
&lt;div class="span4"&gt;
    @_
&lt;/div&gt;
END_HTML
}</code></pre>

<p>(I initially tried to write these functions as templates within Template
Toolkit itself, but there comes a point at which you want a real language. That
point came very early for me.)</p>

<p>I lose no love over the <code>varname = BLOCK</code> pattern necessary to
populate variables to pass to these plugin functions, but it works for now. In
some of my templates&mdash;usually those with lots of text I might end up
changing later&mdash;I extract that text into a separate template under
<em>components/content/</em> to make it easy to edit. (This idea came up during
a client project where the client wanted to edit the legal clickthrough
arrangement after users create accounts. I didn't want lawyers or anyone to
have the ability to mess up the templating language, so I said "Edit this
single file as plain HTML and you'll be fine." It worked great.)</p>

<p>While my programmer brain says "This is ugly, and you're a horrible person
for committing this hack upon the world&mdash;you're calling Perl from your
template system to generate HTML you're stuffing into a template and that puts
your presentation elements in Perl code, you awful human being!", it keeps the
presentation code in a single place where I can update it infrequently (being
that I don't change the layout of the site dramatically) without having to
change the divs and classes of multiple templates.</p>

<p>I'm not arguing that this technique as expressed here is <em>right</em>.
It's probably not optimal; there may be easier approaches to achieve the same
effects.</p>

<p>I am saying that this currently works very well for me. I'm not typing the
same HTML over and over and over again, and I can tweak it much more easily
than I did before when I was refining the look and feel. In fact, I've even
<em>forgotten</em> the exact details of the layout, from the HTML/CSS point of
view, and now think only in terms of rows, maincontent, and sidebars.</p>

<p>Working abstractions are very nice.</p>
        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/05/14/separating-presentation-from-content-in-templates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple Attribute-Based Template Exporting</title>
		<link>http://www.modernperlbooks.com/mt/2012/05/simple-attribute-based-template-exporting.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/05/simple-attribute-based-template-exporting.html#comments</comments>
		<pubDate>Fri, 11 May 2012 20:29:01 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[cpan]]></category>
		<category><![CDATA[modernperl]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[webprogramming]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=8072073cb45a2548172a881d305c3f74</guid>
		<description><![CDATA[If you're like me and your design skills are sufficient to modify something decent to look nice but insufficient to create something from first principles, you can do a lot worse than to play with Twitter Bootstrap for your next...]]></description>
			<content:encoded><![CDATA[
        <p>If you're like me and your design skills are sufficient to modify something
decent to look nice but insufficient to create something from first principles,
you can do a lot worse than to play with <a
href="http://twitter.github.com/bootstrap/">Twitter Bootstrap</a> for your next
web site.</p>

<p>I've used it successfully for a few projects and it's been great.</p>

<p>It's a lot better now that I've written my own silly little <a
href="http://template-toolkit.org/">Template Toolkit</a> plugin to reduce the
need for writing lots of repetitive HTML in my templates. (It's like <a
href="http://haml-lang.com/">Haml</a> but less ugly and more Perlish and easier
to extend.)</p>

<p>Writing a TT2 plugin is relatively easy. Of course I do it the wrong way;
when you initialize your plugin, you have the ability to manipulate TT2's
stash. This is the data structure representing the variables in scope in your
templates. Where a well-behaved template should use object methods to perform
its operations, my code stuffs function references in the stash. Here's the
relevant code:</p>

<pre><code>sub new
{
    my ($class, $context, @params) = @_;

    $class-&gt;add_functions( $context );

    return $class-&gt;SUPER::new( $context, @params );
}

sub add_functions
{
    my ($class, $context) = @_;
    my $stash             = $context-&gt;stash;

    while (my ($name, $ref) = each %exports)
    {
        $stash-&gt;set( $name, $ref );
    }

    $stash-&gt;set( process =&gt; sub { $context-&gt;process( @_ ) } );
}</code></pre>

<p>I'll fix this eventually, but the process of making this work was
interesting.</p>

<p>In my first attempt (see <a
href="http://www.modernperlbooks.com/mt/2012/05/write-the-wrong-code-first.html">Write
the Wrong Code First</a> for the justification), I'd write the function I
needed, like <code>row()</code>, which creates a new Bootstrap row or
<code>maincontent()</code> which creates the main content area of the page.
Then I'd add that function to the <code>%exports</code> hash and everything
would work.</p>

<p>After the sixth function, keeping that list up to date was tedious. Then I
kept forgetting it. After all, any time you have to update the same data in two
places, you're doing something wrong.</p>

<p>Now the code looks more like:</p>

<pre><code>sub row <strong>:Export</strong>
{
    return &lt;&lt;END_HTML;
&lt;div class="row"&gt;
    @_
&lt;/div&gt;
END_HTML
}</code></pre>

<p>... with a single code attribute marking those functions which I want to
stuff into the template stash. I've used <a
href="http://search.cpan.org/perldoc?Attribute::Handlers">Attribute::Handlers</a>
before, but I always end up reading the manual and playing with things to get
them to work correctly. (Something about the way you have to write another
package and inherit from it to get your attributes to work correctly always
confuses me.)</p>

<p>My second attempt lasted no longer than ten minutes. I switched to <a href="http://search.cpan.org/perldoc?Attribute::Lexical">Attribute::Lexical</a>. This is almost as trivial to use as to explain:</p>

<pre><code>use Attribute::Lexical 'CODE:Export' => \&amp;export_code;</code></pre>

<p>Whenever any function has the <code>:Export</code> attribute, Perl wil lcall
my <code>export_code()</code> function:</p>

<pre><code>my %exports;

sub export_code
{
    my $referent = shift;
    my $name     = Sub::Identify::sub_name( $referent );

    return unless $name;
    $exports{$name} = $referent;
}</code></pre>

<p>The first argument to this function is a reference to the exported function.
I use <a href="http://search.cpan.org/perldoc?Sub::Identify">Sub::Identify</a>
to get the name of the function reference. (That wouldn't work for anonymous
functions, but I can control that here.) Then I store the name of the function
and the function reference in a hash.</p>

<p>It took as long to write as it does to explain.</p>

<p>A lot of people dislike the use of attributes. Used poorly, they create
weird couplings and plenty of action at a distance.
<code>Attribute::Handlers</code> can be confusing.</p>

<p>I like to think that I'm using attributes well here (even if I'm abusing TT2
more than a little), and that they've simplified my code so that I can avoid
repeating myself and performing manual busywork that I'm likely to forget. Even
better, the code to use them isn't magical at all: it's all hidden behind the
pleasant interfaces of <code>Attribute::Lexical</code> and
<code>Sub::Identify</code>.</p>
        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/05/11/simple-attribute-based-template-exporting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Write the Wrong Code First</title>
		<link>http://www.modernperlbooks.com/mt/2012/05/write-the-wrong-code-first.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/05/write-the-wrong-code-first.html#comments</comments>
		<pubDate>Wed, 09 May 2012 18:37:54 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[softwaredevelopment]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=010a0610d65c8776ce568928a4bd6fbe</guid>
		<description><![CDATA[I rewrite code often. If I were a better programmer, designer, or businessman, I would rewrite my code much less frequently&#38;mdash;but I get things wrong about as often as I get them right. Even with years of practical experience, software's...]]></description>
			<content:encoded><![CDATA[
        <p>I rewrite code often.</p>

<p>If I were a better programmer, designer, or businessman, I would rewrite my
code much less frequently&mdash;but I get things wrong about as often as I get
them right. Even with years of practical experience, software's still too
difficult to predict with any degree of accuracy.</p>

<p>As a case in point, I've been revising some financial software in the past
week. In reviewing the calculations, I found a way to simplify them
dramatically.  Even better, these simplifications allow me to simplify the
interface and user experience.</p>

<p>That means rewriting a lot of code. That means throwing out code and
revising the storage model and making a lot of changes.</p>

<p>I'm fortunate to have a good test suite that runs in 15 to 20 seconds and
lets me know that everything I most need to work continues to work. That's a
lot of confidence. People who like to talk about test-driven development and
refactoring tout this as one of the benefits of well-tested software: you can
refactor with confidence.</p>

<p>I'm not refactoring. I'm throwing away parts of this application and adding
others. I'm changing how it behaves. Even though my test suite helps, that's
not refactoring.</p>

<p>As part of this project, I've added an SVG graph to a class of web pages. I
started by creating the SVG in Inkscape. Then I exported it as plain SVG. Then
I made a template for that SVG to include from the page template.</p>

<p>That was still the example SVG with sample data, still the proof of
concept.</p>

<p>I then extracted one piece of hard-coded data and made it a templated value.
One. Everything still worked. Then I extracted the second piece of data and so
on.</p>

<p>It's one step at a time. It's one change at a time. I'm using Git, so I
could even commit after every single change, no matter that it's a few
characters or even merely changing the color of a bar in the graph. I can work
in steps as small and discrete as possible, and then squash them into one big
commit or rewrite them into functional units, or do whatever I want with
them.</p>

<p>That's the same principle behind test-driven development (or test-driven
design or even behavior-driven development, if you need to hang a new name on
the same idea). Do one thing at a time. Make your code do a little more of what
it needs to do. Prove that it all hangs together, that it all works, that it
does what you intended.</p>

<p>Then clean up a little bit. That's refactoring, in your code and in your
tests. That's rebasing in Git.</p>

<p>Sure, I wish I could know exactly what I needed to write from the start. I
wish sometimes that programming were mere transcription of the voice of an
ephemeral muse (though I find it difficult to imagine a muse dictating Perl or
JavaScript or Haskell or J aloud). I wish I were the Beethoven of programming
(without the mercurial temperament and the hearing loss).</p>

<p>Usually I don't get things right from the start. Fortunately, a little
discipline and the willingness to work in small steps, to erect and replace the
scaffolding as I go, and I usually get a lot closer to the right code than
if I guessed.</p>

<p>Maybe that means I've thrown out more code than I've written. (It's satisfying to delete unused code, after all.) Maybe any project which starts as a proof of concept, then has to pivot in other directions to do what it's always needed to do always becomes a <a href="http://faculty.washington.edu/smcohen/320/theseus.html">Ship of Theseus</a>.</p>

<p>I'm okay with that. It's more important to me to create something useful and
then make it right than to wait on getting it right before other people can
find value in it. I may never write the right code from the start, but I
believe I can make almost-right code much, much more right, with discipline and
care and feedback.</p>
        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/05/09/write-the-wrong-code-first/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NYTProf, File IO, and an Optimization Gone Awry</title>
		<link>http://www.modernperlbooks.com/mt/2012/05/nytprof-file-io-and-an-optimization-gone-awry.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/05/nytprof-file-io-and-an-optimization-gone-awry.html#comments</comments>
		<pubDate>Mon, 07 May 2012 21:56:41 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[cpan]]></category>
		<category><![CDATA[modernperl]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[profiling]]></category>
		<category><![CDATA[softwaredevelopment]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=ce8793e9ef2fc7b17ac9464159a79cc7</guid>
		<description><![CDATA[One of my projects performs a lot of web scraping. Once every n units of time (where n can be days or weeks), a batch process fetches several web pages and extracts information from them. It's a problem solved very...]]></description>
			<content:encoded><![CDATA[
        <p>One of my projects performs a lot of web scraping. Once every <em>n</em>
units of time (where <em>n</em> can be days or weeks), a batch process fetches
several web pages and extracts information from them. It's a problem solved
very well.</p>

<p>I designed this system around the idea of a pipeline of related processes,
where each component is as independent and idempotent as possible. This has
positives and negatives; it's an abstraction like any other.</p>

<p>I initially wrote the "fetch remote web page" and "analyze data from that
page" as a single step, because I thought "analyze" was the main goal and
"fetch" was a dependent task. I separated them a couple of weeks ago to
simplify the system: analysis now expects data to be there, while fetching can
be parallel on a single or across multiple machines. (Testing the analysis step
is also much easier because feeding in dummy data is now trivial.)</p>

<p>I use the filesystem as a cache for these fetched files. That's easy to
manage. I modified the role I use to grab data for the analysis stage to look
in the cache first, then fall back to a network request. That was easy too. The
<code>get_formatted_data_for_analysis()</code> method looked something like:<p>

<pre><code>sub get_formatted_data_for_analysis
{
    my ($self, $type, $key) = @_;

    my $cached_path         = $self-&gt;get_cached_path( $type, $key );
    if (-e $cached_path)
    {
        my $text = read_file( $cached_path );
        return $self-&gt;formatter-&gt;format_string( $text ) if $text;
    }

    return $self-&gt;formatter-&gt;format_string( $self-&gt;fetch_by_url( $type, $key ) );
}</code></pre>

<p>I thought I was done. This trivial caching layer took five minutes to write and gave my project a lot of flexibility.</p>

<p>I thought this would speed up the processing stage, because I was able to
make the fetching stage embarrassingly parallel so that more than one fetch
could block on network IO simultaneously. My rough benchmark didn't show any
speed improvement, but it was fast enough, so I moved on.</p>

<p>On Friday I decided to profile the slowest stage of the application with <a
href="http://search.cpan.org/perldoc?Devel::NYTProf">Devel::NYTProf</a>. The
slowest stage was the processing stage. I isolated it so that it performed no
network fetching. It was still slow.</p>

<p>One of the formatter modules used to extract data from web pages is <a
href="http://search.cpan.org/perldoc?HTML::FormatText::Lynx">HTML::FormatText::Lynx</a>.
It allows me to run <code>lynx --dump</code> to strip out all of the HTML and
other formatting of a document. The formatter allows you to pass in the name of
a file or the contents of a file as a string.</p>

<p>For some reason, most of the time in the processing stage in the profile was
spent in file IO. That wasn't too surprising; these aren't all small files and
there may be thousands of them. I dug deeper.</p>

<p>Most of the time in the processing stage in the profile was spent in reading
the files in my method and reading files in the formatter&mdash;reading files,
even though I was passing the contents of those files to the formatter as
strings.</p>

<p>I poked around at a few other things, but came back to the source code of
the formatter. A comment in <a
href="http://search.cpan.org/perldoc?HTML::FormatExternal">HTML::FormatExternal</a>
says:

<blockquote><code>format_string()</code> takes the easy approach of putting the
string in a temp file and letting <code>format_file()</code> do the real work.
The formatter programs can generally read stdin and write stdout, so could do
that with <code>select()</code> to simultaneously write and read
back.</blockquote>

<p>In other words, all of the work I was doing to read in files was busy work,
duplicating what the formatter was about to do anyway. (Okay, I stared at the
code for a couple of minutes, thinking about various approaches of rewriting it
and submitting a patch or monkey patching it. Then I turned lazier and wiser.)
I rewrote my code:</p>

<pre><code>sub get_formatted_data_for_analysis
{
    my ($self, $type, $key) = @_;

    my $cached_path         = $self-&gt;get_cached_path( $type, $key );
    return $self-&gt;formatter-&gt;format_file( $cached_path ) if -e $cached_path;

    return $self-&gt;formatter-&gt;format_text( $self-&gt;fetch_by_url( $type, $key ) );
}</code></pre>

<p>The result was a 25% performance improvement.</p>

<p>Three things jumped out at me in this process. First, how nice is it to have
a working tool like NYTProf and a community that distributes source code, so
that I could examine the whole stack of my application to isolate performance
problems? Second, how interesting that an assumption and an admitted shortcut
in a dependency could have such an effect on my own code. Third, how much more
I like my new code with all of the file handling gone; pushing that
responsibility elsewhere is a nice simplification without the performance
improvement.</p>

<p>Perhaps the two tools I miss most from my C programming days are
Valgrind/Callgrind and KCachegrind, but NYTProf goes a long way toward filling
that gap. Besides, I'm at least 20 times more productive with a language like
Perl.</p>

        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/05/07/nytprof-file-io-and-an-optimization-gone-awry/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Perlbuzz news roundup for 2012-05-07</title>
		<link>http://feedproxy.google.com/~r/PerlBuzz/~3/o9hwMDipS2Y/perlbuzz-news-roundup-for-2012-05-07.html</link>
		<comments>http://feedproxy.google.com/~r/PerlBuzz/~3/o9hwMDipS2Y/perlbuzz-news-roundup-for-2012-05-07.html#comments</comments>
		<pubDate>Mon, 07 May 2012 14:26:45 +0000</pubDate>
		<dc:creator>Andy Lester</dc:creator>
				<category><![CDATA[cpan]]></category>
		<category><![CDATA[Perl 5]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=d4e6f45e180c8a72b23bd749b89b61c3</guid>
		<description><![CDATA[These links are collected from the Perlbuzz Twitter feed. If you have suggestions for news bits, please mail me at andy@perlbuzz.com. Always encode and decode Unicode at the edges of your program (perl.com) mod_perl 2.0.6 released (blogs.perl.org) Comments are...]]></description>
			<content:encoded><![CDATA[
        <p>
These links are collected from the
<a href="http://twitter.com/perlbuzz">Perlbuzz Twitter feed</a>.
If you have suggestions for news bits, please mail me at
<a href="mailto:andy@perlbuzz.com">andy@perlbuzz.com</a>.
</p>

<ul>

<li>Always encode and decode Unicode at the edges of your program (<a href="http://www.perl.com/pub/2012/05/perlunicook-make-file-io-default-to-utf-8.html">perl.com</a>)</li>
<li>mod_perl 2.0.6 released (<a href="http://blogs.perl.org/users/phred/2012/05/mod-perl-206-released.html">blogs.perl.org</a>)</li>
<li>Comments are open on the Perl Foundation's latest grant proposals (<a href="http://news.perlfoundation.org/2012/05/2012q2-grant-proposals.html">news.perlfoundation.org</a>)</li>
<li>Creating weekly schedule charts with HTML::Template (<a href="http://blog.nu42.com/2012/05/generate-pretty-weekly-schedule-chart.html">blog.nu42.com</a>)</li>
<li>Playing music with Audio::Beep (<a href="http://blog.und3f.com/joy-of-the-internal-speaker">blog.und3f.com</a>)</li>
<li>Tad McClellan has passed away (<a href="http://blogs.perl.org/users/brian_d_foy/2012/05/tad-mcclellan-rip.html">blogs.perl.org</a>)</li>
<li>Coding before having expert-level understanding is OK (<a href="http://www.modernperlbooks.com/mt/2012/05/smoothing-the-condescending-onramp.html">modernperlbooks.com</a>)</li>
</ul>

        
    <div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=o9hwMDipS2Y:Ogho2fJNLTE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/PerlBuzz?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=o9hwMDipS2Y:Ogho2fJNLTE:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/PerlBuzz?i=o9hwMDipS2Y:Ogho2fJNLTE:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=o9hwMDipS2Y:Ogho2fJNLTE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/PerlBuzz?i=o9hwMDipS2Y:Ogho2fJNLTE:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/PerlBuzz?a=o9hwMDipS2Y:Ogho2fJNLTE:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/PerlBuzz?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/PerlBuzz/~4/o9hwMDipS2Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/05/07/perlbuzz-news-roundup-for-2012-05-07/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Smoothing the Condescending Onramp</title>
		<link>http://www.modernperlbooks.com/mt/2012/05/smoothing-the-condescending-onramp.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/05/smoothing-the-condescending-onramp.html#comments</comments>
		<pubDate>Wed, 02 May 2012 21:42:28 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[codingstandards]]></category>
		<category><![CDATA[modernperl]]></category>
		<category><![CDATA[novices]]></category>
		<category><![CDATA[perl]]></category>
		<category><![CDATA[training]]></category>
		<category><![CDATA[tutorials]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=d0bec1efeae94194d5b907c840f6b5c5</guid>
		<description><![CDATA[If you ever need a dose of humility, solve a non-trivial problem and then watch a Real Actual User try to figure out how to use it. In my second professional job, when I was a system administrator at HP,...]]></description>
			<content:encoded><![CDATA[
        <p>If you ever need a dose of humility, solve a non-trivial problem and then
watch a Real Actual User try to figure out how to use it.</p>

<p>In my second professional job, when I was a system administrator at HP, I
worked in the laser printer group. One afternoon, someone walked by my desk and
asked me to do a user interaction study. I followed her to a little lab area,
where she handed me a list of tasks, and asked me to complete them.</p>

<p>I did, except that I misread the icon on the copier and put in the source
pages upside down, and made ten warm and blank pieces of paper. As soon as that
happened, I <em>understood</em> the icon and why I'd misinterpreted it.</p>

<p>I never heard the results of the study, but I hope my stubborn confusion
ended up improving the product.</p>

<p>User experience (and <em>real</em> user experience, not the fake user
experience stuff that says users are clueless and incapable of all of the
complexity of navigating the cereal aisle of an American grocery store and thus
interfaces must degenerate to a single beveled button which says "DO IT", do
you like my black turtleneck?) is fascinating. What's clear to you, you who
understand the internal model of the software, is perfectly opaque to users. <a
href="http://www.modernperlbooks.com/mt/2011/11/promoting-perls-features-versus-benefits.html">Users
know the results they want</a>, but not necessarily how to achieve them.</p>

<p>Making things easy for novices&mdash;for people who don't have a correct
internal model of the software&mdash;can be compatible with making powerful
software. Consider the <a
href="http://www.perl.com/pub/2012/04/perlunicook-standard-preamble.html">Perl
5 standard Unicode preamble</a> necessary to convince Perl to use the defaults
you probably want to handle anything-but-Latin-1 correctly.</p>

<p>(When user complaints of "My code doesn't work!" get met on PerlMonks and
the Perl Beginners List and elsewhere with "What's the error message?", you
know the languages, libraries, tools, and ecosystem could do more to help
people debug their own code.)</p>

<p>You see the problem when books and other tutorial materials say "Error
checking is left as an exercise for the reader", as if the burden of writing
correct code or the increased page count is far more important than the desire
to help new programmers learn how to code well.</p>

<p>I'm not only talking about better defaults (like <code>strict</code> enabled with <code>use 5.014;</code>). I'm not only talking about writing and collecting <a href="http://perl-tutorial.org/">good Perl tutorials</a>. (Part of the reason <a href="http://modernperlbooks.com/books/modern_perl/">Modern Perl: the Book is available for free online</a> is to continue to cultivate the culture of making great tutorial material available to anyone and everyone.)</p>

<p>With that said, I do despise the attitude of "You have to be clueful enough
to use the proper incantation at the start of your programs before you'll get
help on PerlMonks". Sure, those of us who know Perl <em>now</em> had to learn
the hard way that symbolic references and global variables make our code harder
to manage, that a unified testing system can only improve the CPAN, and that
agreeing on an interoperable OO syntax (if not implementation) lets us
concentrate on solving problems, not rebuilding Greenspun frameworks, but
that's no reason to force the same learning curve on novices.</p>

<p>We'll never remove the essential complexity from programming (to do so would
require us to remove the essential complexity from the problems we're trying to
solve). We <em>can</em> smooth out the onramp for new programmers. That
requires us to think like new programmers and to understand what they're trying
to do and why.</p>

<p>Sometimes that recommends that those of us who see a question and think
"Wow, everyone knows how to use a hash! What's <em>wrong</em> with you for not
understanding this?" to shut up. (Sometimes the best person to help a new
programmer is someone who was recently new.) Often times that requires us to
listen and look for the deeper question.</p>

<p>That <em>probably</em> recommends us to be a little gentler on the audiences
we reach when we publish text and code. As Tom Dale wrote in <a
href="http://tomdale.net/2012/04/best-practices-exist-for-a-reason/">Best
Practices Exist for a Reason</a>:</p>

<blockquote>writing code before you have an expert-level understanding is okay.</blockquote>

<p>(The whole post and its comments are... enlightening.)</p>

<p>Ultimately I expect the real point is to know who you're writing for. If
you're only ever writing for your own amusement and you're willing to cut off
everyone who doesn't share your level of knowledge, that's one thing. If you're
writing to help other people&mdash;even if they have just started using Perl
today&mdash;perhaps there are ways you can smooth the onramp for them a little
bit more. After all, the things we think are easy now are because we understand
the intricacies of lexical binding and scope and default topicalization and
eager versus iteration file reading and so on.</p>
        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/05/02/smoothing-the-condescending-onramp/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Picking Functional Programming&#8217;s Pockets</title>
		<link>http://www.modernperlbooks.com/mt/2012/04/picking-functional-programmings-pockets.html</link>
		<comments>http://www.modernperlbooks.com/mt/2012/04/picking-functional-programmings-pockets.html#comments</comments>
		<pubDate>Mon, 30 Apr 2012 19:49:43 +0000</pubDate>
		<dc:creator>chromatic</dc:creator>
				<category><![CDATA[design]]></category>
		<category><![CDATA[functionalprogramming]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[laziness]]></category>
		<category><![CDATA[modernperl]]></category>
		<category><![CDATA[purity]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://perlblogs.com/?guid=4665bcfaeb4de72be73c62ebd1976eb2</guid>
		<description><![CDATA[In all of the debates over whether pair programming is exclusively 100% good or exclusively 100% evil or whether test-driven design is exclusively 100% beneficial or exclusively 100% silly, people sometimes miss the nuances of the polemic &#34;if it's hard...]]></description>
			<content:encoded><![CDATA[
        <p>In all of the debates over whether pair programming is exclusively 100% good
or exclusively 100% evil or whether test-driven design is exclusively 100%
beneficial or exclusively 100% silly, people sometimes miss the nuances of the
polemic "if it's hard to test, it's hard to use".</p>

<p>In practice, that means that good programmers with good taste built from
painful experiences have the ability to write better code if they exercise good
taste when building tests.</p>

<p>(I know, this is the Internet of 21st century culture; the law of the
excluded middle suggests that nuance, like irony, is deader than 19th century
utopian cults. Doesn't mean that 10,000 volts of CPR are <em>always</em>
wasted.)</p>

<p>That's what I had in mind when I wrote <a
href="http://www.modernperlbooks.com/mt/2012/04/mock-objects-despoil-your-tests.html">Mock
Objects Despoil Your Tests</a>. (See also Martin Fowler's <a
href="http://martinfowler.com/articles/mocksArentStubs.html">Mocks Aren't
Stubs</a>.)</p>

<p>The more gyrations your code has to undergo before you're confident that it
does what you intend it to do, no more and no less, the less confidence you
have overall. In highfalutin' architecture astronaut terms, the more tightly coupled your tests are to the internals of your code, the worse your tests are. They could be fragile. They could make too many assumptions. They could be exercising things that no real code would exercise. They could be hard to write and overspecific.</p>

<p>In short, the likelihood that you've built yourself a maintenance burden is
higher when you know far too much about the internals of a thing outside of
that thing, even if the thing on the outside is a test intended to give you
confidence.</p>

<p>(That's why I distrust putting code and tests in the same file, thank you
very much Java. It's too tempting to cheat when the clear lines of demarcation
aren't there.)</p>

<p>I only realized what I've been doing lately when I read Buddy Burden's <a
href="http://blogs.perl.org/users/buddy_burden/2012/04/lazy-cache.html">Lazy ==
Cache?</a>. He describes Moose lazy attributes the way I see them: as a promise
to provide information when you need it. That laziness is a hallmark of
Haskell. If you take laziness as far as Haskell does, you can build amazing
things where things just happen when you need them.</p>

<p>Haskell, of course, goes a long way to encourage you to write programs in a
pure style, where functions don't have side effects. Data comes into a function
and data goes out, and the state of the world stays unchanged. Sure, you can't
write any interesting program without at least performing IO, but Haskell
encourages you to embrace purity as much as possible such that you minimize the
places you update global state.</p>

<p>In my recent code, this has also just sort of happened, even in that code
which isn't Haskell.</p>

<p>Consider an application which tracks daily stock market information, such as
price and market capitalization. Each stock is a row in a table modeled by <a
href="http://search.cpan.org/perldoc?DBIx::Class">DBIx::Class</a>. Each stock
has an associated state, like "fetch daily price" or "write yearly free cash
graph" or "invalid name; review".</p>

<p>No one would fault you for updating the stock price, market cap, and state
on a successful fetch from the web service which provides this information.
That's exactly what I used to do.</p>

<p>Now I don't.</p>

<p>I've separated the fetching of data from the parsing of data from the
updating of data. Fetching and updating are solved problems; they happen at the
boundaries of my code and I can only control so much about them. Either the
database works or it doesn't. Either the remote web service is up or it isn't.
(I still test them, but I've isolated them as much as possible.)</p>

<p>The interesting thing is always in the parsing and analysis. This is where
all of the assumptions appear. (Is Berkshire Hathaway's A class
<code>BRK.a</code> or <code>BRK-A</code> or something else? Are abbreviations
acceptable in sector and industry classifications?) This is where I want to
focus my testing&mdash;even my ad hoc testing, when I've found an assumption
but need to research what's gone wrong and why before I can formalize my
solution in test cases and code.</p>

<p>This means, the daily analysis method looks something like:</p>

<pre><code>sub analyze_daily
{
    my ($self, $stock, $updates) = @_;
    my $stats                    = $self-&gt;get_daily_stats_for( $stock-&gt;symbol );

    return unless $stats-&gt;{current_price};
    $updates-&gt;{current_price} = $stats-&gt;{current_price};

    return unless $stats-&gt;{market_capitalization};
    $updates-&gt;{market_capitalization} = $stats-&gt;{market_capitalization};

    $updates-&gt;{PK} = $stock-&gt;symbol;
    return 1;
}</code></pre>

<p>Any code that wants to test this can pass in a hash reference for
<code>$updates</code> and a stock object (or equivalent) in <code>$stock</code>
and test that the results are sane by exploring the hash reference directly,
rather than poking around in <code>$stock</code>.</p>

<p>(The data fetcher itself uses dependency injection and fixture data so that
all expected values are known values and that network errors or transient
failures don't affect this test; obviously other tests must verify that the
remote API behaves as expected. While I could make <code>$stats</code> a
parameter here, I haven't had the need to go that far yet. There's a point
beyond removing dependencies from inside a discrete unit of code makes little
sense.)</p>

<p>This code is also much more reusable; it's trivial to create a <em>bin/</em>
or <em>script/</em> directory full of little utilities which use the same API
as the tests and help me debug or clean up or inspect all of this wonderful
data.</p>

<p>Better yet, I find myself needing fewer tests, because each unit under test
does less and has fewer loops and conditionals and edge cases. The problem
becomes "What's the right fixture data to exercise the interesting behavior of
this code?" My tests care less about managing the state of the objects and
entities under test than they do about the transformations of data.</p>

<p>Perhaps it's not so strange that that's exactly what my programs care
about too.</p>
        
    ]]></content:encoded>
			<wfw:commentRss>http://perlblogs.com/2012/04/30/picking-functional-programmings-pockets/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

