10 Things I Love/Hate About Movable Type

| No Comments

I have a love/hate relationship with my blogging tool. Here are ten aspects of Movable Type about which I am emotionally conflicted.

  1. Love: Movable Type is implemented in Perl. Yay, Perl!
    Hate: Movable Type is implemented in "old school" Perl, not Modern Perl. (But they are working on that, thanks MT team!)

  2. Love: Movable Type's publishing engine supports many publishing modes, including scheduled posts, and publishes static HTML files by default for efficient hosting.
    Hate: The only option for dynamic publishing is - PHP? Seriously? Sorry MT, I fully understand the business reasons behind this, but as a Perl developer, it still offends me.

  3. Love: Movable Type is themeable.
    Hate: The default theme is ugly. Replacement themes are not much better, so I'm still using the default.

  4. Love: Movable Type fully supports post metadata, without overwhelming you with interface inputs (not a unique feature of MT, but a nice one).
    Hate: MT has three distinct metadata items called Categories, Tags, and Keywords. Each behaves differently, despite the fact that they all mean approximately the same thing to a user. (Tip: Categories generate pages. Tags do not, but are searchable. Keywords are basically useless.)

  5. Love: Input filters allow you to compose your posts using Markdown, Textile, or plain HTML.
    Hate: The built-in editor is just as clunky as all web-based editors (a problem not unique to MT). But worse, it feels "bolted on" rather than integrated into the blogging system. For example, there is no tool to easily create links to other posts. If you want to link to a previous post, you have to go look up the URL yourself (which is not easy due to the information architecture of the site, see below).

  6. Love: Plugins and The Registry - Everything revolves around this central "registry" data structure. Once you understand that structure and how to tweak it, you can do some pretty cool things without a lot of code. As a matter of fact, you don't even need to write Perl anymore, you can just drop a yaml file in a directory and it gets slurped into the data structure.
    Hate: Managing plugins is a huge pain. In order for them to work you have to mix the plugin files with the original MT code in the same directory. You're never really sure if you're overwriting something, and if you do, you're SOL. Upgrading MT or one of the plugins also becomes painful, because it's hard to tell which files are core and which plugin. I took to managing mine with stow, which made it livable, but still horrible. Plus, half the plugins available only work with the ancient MT3, not the more modern MT4.

  7. Love: The flexible template system. Once you get the hang of it, it's easy to make template tags produce all kinds of nifty things. And it is possible (though not trivial) to create new tags via plugins if you need additional functionality.
    Hate: Templates are stored in the database by default, not the file system. This means you have to use the clunky MT template editor to edit them any time you change, or use the clunky MT template editor to edit every single template individually to force them to live in the filesystem. (Or write a script to fix it.) And you have to remember to do this every time you create a new blog too.

  8. Love: Every template is customizable, and you can make as many as you want.
    Hate: As soon as you customize a template, you have to start worrying about your changes getting clobbered if you "refresh" to get new MT templates, which you really have to do if you want to take advantage of new MT features. (At least MT makes backups for you by default. But since they are stored in the database and not the filesystem, they are a pain to deal with.)

  9. Love: Movable Type supports multiple blogs/sites in the same installation, and as a result it is possible to craft queries in your templates that aggregate multiple blogs.
    Hate: Each blog always gets its own separate set of templates based on an original core set. Sharing individual templates across blogs is hard. Sharing a whole set of templates requires bending over backwards and nibbling your heels. Making an identical set of changes to identical non-shared templates requires a custom Perl script, or the patience of Job.

  10. Love: Movable Type's default template set is built with web standards: XHTML, CSS, and even microformats, with progressive enhancement in Javascript.
    Hate: The information architecture of the default template set is terrible. Navigation is stuck into a sidebar down the page instead of up front. Pages that list posts always include the full text of a post rather than just a pointer, making exploration and discovery difficult. The whole site architecture seems to have been inherited unchanged from whatever protozoic blog first emerged from the muck back in the Paleo-web of the "Dot Com Bubble" era.

Glad I got that off my chest. What's your boggle?

The Moose is on fire!

| No Comments

Matt S. Trout suggested that we Perl people should be posting to our blogs weekly, rather than weakly. It's hard to argue against that, so here's my first in an attempted string of weekly posts. Cross your fingers!

This week I was strongly inspired by all the yummy goodness happening around the Moose project. The Catalyst framework is now officially based on Moose, and John Napiorkowski is writing a Catalyst app in public to show it off. Meanwhile Jonathan Rockway did some showing off too (okay, before this week, but I just caught up on my feeds), using a URL un-shortening service as an excuse to put some swank Moose extensions out front. And chromatic also had some great stuff to say about concision in Perl, a subject on which I have spoken as well.

With both jrock and chromatic writing about how cool MooseX::Declare is, it got me itching to try it out for myself. I've been way too busy for hobby coding in the last couple of months, and that's just bad for a Perl geek's mood. So this week I'm going to make some time for my passion and carve out a script I've been wanting, and I'm going to do it with MooseX::Declare for that warm and fuzzy feeling. So I'm going to take a spin through the new Moose documentation that Dave Rolsky just finished, and then get cracking. If it all works out, you'll hear about it next week!

What do you get if you cross Perl CGI with Mod-PHP?

| No Comments

One possibility is mod_perlite, an Apache module that aims to make Perl as easy as PHP for users to deploy and for service providers to host.

I love mod_perl and use it every day, but the fact is that most web hosts don't give their customers access to it, precisely because it is so powerful (and complex). But old-school CGI scripts with their fork-and-exec model are slow and resource intensive. This has left an opening into which PHP has stepped as the "upload your files and you're done" language for web development.

The JAPHs over at modperlite.org are looking for some help. If you know your way around Perl and/or Apache internals, or are looking for an excuse to learn, they would love to hear from you. Go "git" the code, join the group, and lend a hand!

HTML::Mason is a template system with power tools built in. Here's a case study in the usefulness of Mason's internal caching tools.

Mason reads from database

As part of a web site registration application, the user is to be presented with a list of email newsletters the site makes available. During registration, the user may select one or more of the newsletters and be automatically subscribed. So I coded up a Mason component to display this list.

<%once>
use ListDB;
</%once>
<%init>
my @newsletters = ListDB::get_mailing_lists();
</%init>
% for my $newsletter (@newsletters) {
    <input id="subscribe" type="checkbox" name="subscribe" value="<% $newsletter %>">
    <label for="subscribe"><% $newsletter %></label><br>
%}

Of course this example is simplified, the real code has more HTML and a bit more display logic. It's not pretty, but it gets the job done. In the once section I import the library that interfaces with our mailing list database (which is managed by a separate application). Then we simply get a list of available newsletters and display each with an input checkbox.

When database is busy, Apache gets tied up!

As the website and the newsletters became more popular, we began to see problems. Specifically, when the mailing list software was performing some database intensive task, as it frequently did, the simple query underlying the call to ListDB::get_mailing_lists() would take a very long time to return. As a result, the user had to wait a minute or more for the page to load, and an Apache process was occupied waiting for the database to return. If we ever had a time when the web site and the database were both busy at the same time, all our Apache processes could end up waiting for the database query, leaving none to serve pages. That's bad news for a web site!

The problem here, obviously, is that the code queries the database every time a user requests the registration form. This is not a problem that is unique to Mason, all dynamic web applications eventually run into it. Nor is the solution unique to Mason. But Mason makes the solution trivial to implement.

Mason cache smoothes database bumps

The solution, of course, is to cache the response from the database, so that the next web request does not need to hit the database in order to render the list. The list of newsletters doesn't change very often, so there is no harm in caching it. In fact, since the HTML rendering of the list won't change either, why not cache the HTML and save the rendering next time too?

If only Mason had a built-in cache system so I wouldn't have to go digging around for extra modules on CPAN and write another 20 lines of code. Oh wait, it does!

<%init>
return if $m->cache_self(expire_in => 3600); # THE SOLUTION! (ALMOST)
require ListDB;
my @newsletters = ListDB::get_mailing_lists();
</%init>
% for my $newsletter (@newsletters) {
    <input id="subscribe" type="checkbox" name="subscribe" value="<% $newsletter %>">
    <label for="subscribe"><% $newsletter %></label><br>
%}

See, I told you Mason makes it easy! You can arrange for any component to cache its output with this simple incantation. If the component has previously been cached, $m->cache_self will return a true value, and the component will not execute again. Instead, the output will be fetched from the cache, without any further action on your part. Pretty neat, huh? But that's not all it does. If the component has not been previously cached, this routine will set a "hook" that will transparently cache the output of the current component execution once it has finished. Now that's just cool! I'll bet you can guess what the expire_in argument does. Yup, I'm telling it to cache the output for 3600 seconds (one hour), if the current cache happens to be empty.

Notice the other change I made. Instead of useing our ListDB library in the once section, I have changed to a require statement. Why? Because in the general case, the library will not be needed for as much as an hour, because the content will be served from the cache. To save memory, we don't import the library until after the call the $m->cache_self, when we know we'll need it.

After the cache expires, le deluge

Ah, but there's a flaw in your brilliant plan, I hear you say. What happens if the database happens to be slow just when the cache expires? You're right back where you started, with an empty cache and a whole bunch of Apache process waiting for data to fill it with.

Doggone it, why do you have to be so observant? I guess I'll have to break another tool out of Mason's bag of tricks. Watch this!

<%init>
return if $m->cache_self(expire_in => 3600, busy_lock => 60); # THE SOLUTION!
require ListDB;
my @newsletters = ListDB::get_mailing_lists();
</%init>
% for my $newsletter (@newsletters) {
    <input id="subscribe" type="checkbox" name="subscribe" value="<% $newsletter %>">
    <label for="subscribe"><% $newsletter %></label><br>
%}

See what I did there? No? Look again at that first line of the init section. The new busy_lock argument is the key. Basically, that's telling the Mason cache, "Hey, if this object has expired, extend the life of the old cached value by 60 seconds so other processes will still get a cached value. Meanwhile, I'm gonna calculate a new value and cache that."

Now, when the cache "expires", only one Apache process will notice that fact. That one process will proceed to hit the database for the new value. Meanwhile, other processes will continue to find the old value in the cache for another 60 seconds. If the database does happen to be slow, only one user (per minute) will have a problem, and only one apache process will be hung waiting for data.

HTML::Mason references

Perl: Readability, Expressiveness, and Concision

| No Comments
Writing readable code means expressing yourself as clearly and correctly as you can, not targeting the lowest common denominator of reader.

There are many people out there who are preaching the gospel of readable code. I myself am one of them. I am a strong proponent of expressive variable and subroutine names, for example. Unless you are a fire-and-forget contract programmer, you are going to be reading your code a lot more often than you write it. But honestly, if code readability is your primary concern, use Python, not Perl.

Reading good Python code is like reading a novel by Dan Brown or Michael Crichton. The language is clean and simple, allowing you to move forward easily, and quickly grasp the point of the story. The vocabulary is easily attainable and won't stretch your brain too far. I like reading Python code. It's an easy read — a beach read.

Reading good Perl code is like reading Shakespeare. Every line is deeply expressive, both in its content and its rhythm. You probably need a dictionary to look up some words that, while not perhaps in everyday usage, express exactly what the author intended. It's still English, but you have to work a little harder at reading it, because it's beautiful, powerful English.

When I write code, I am concerned about readability. But I am also concerned about expressiveness and concision. I have something I am trying to say. I don't always want two paragraphs of easy prose that approximate my point. Most of the time I want le mot juste, just the right word, a precise expression of exactly what I mean that requires no further elaboration.

Now, I don't intend to imply that my Perl is of a class with Shakespeare's verse (nor Flaubert's prose). What I am saying is that some stories cannot be told in terms of Dick and Jane and Spot. Complex problems often require complex language to describe their solutions. I love writing such solutions in Perl, because Perl, like English, offers me a broad and rich vocabulary of idiom I can use to construct complex works easily.

Those who speak pidgin-Perl can usually puzzle out what the code is doing, but they are going to get hung up at some points, and they are going to miss a lot of detail. That is not a flaw in the language, nor an error on the part of the writer. It is simply the nature of the form. But those who understand the depth of the language can truly appreciate the subtlety of a nice, tight hack.

The key to writing code that is both readable and expressive is to build a bridge with your comments that help the unfamiliar reader find his way through the complex and obscure portions. If you find yourself using a rare or arcane idiom because its the right thing to do, don't dumb it down into fifty lines of loops for novice programmers. Instead, write a full paragraph of explanation above your one-line hack. Include references to man pages, books, and web sites. Scholarly works always have footnotes. The reader will not only gain a better understanding of your code, but perhaps learn a new technique that improves his own.

Writing readable code does not mean writing for the lowest common denominator of reader. It means expressing your point as clearly and correctly as you can. Try to make your code readable, but don't sacrifice concision for readability. You should expect more from your reader, rather than expecting less from your code.

P.S. For another view on the subject, you can read about the Unobfuscated Perl Code Contest.

P.P.S. For more deep(?) thoughts about Perl programming from Webquills.net, read the feed or get new posts via email.

Creative Commons License
This blog is licensed under a Creative Commons License.