Declarative Perl

I'm making rapid progress in getting OokOok to a stable programming scheme. I haven't made a lot of changes in its capabilities, though I did add the ability to archive themes and projects as Bagit files yesterday, I've been working on making the important stuff declarative. By hiding all the details behind a veneer of relationships, I can fiddle with how I manage those relationships without having to touch every relationship every time I make a change in the underlying schemas (and schemes).

For those used to an older style of Perl programming, this might come as a surprise. For those who have dealt with things like MooseX::Declare and CatalystX::Declare, you'll be shaking your head at my foolhardiness in jumping into making an OokOok:Declare that hides the details of how to construct certain types of classes.

Behind the scenes, OokOok consists of controllers, models, views, REST collections/resources, SQL result objects, a template engine, and tag libraries for the templates. Almost two hundred classes in all.

If I built all of these the usual Perl way, there'd be a lot of boilerplate code around. By moving to a declarative approach, I can isolate all the boilerplate in a few core meta-classes. When the boilerplate has to change, I only have to touch one place. Everything else comes along for the ride.

For the rest of this post, I want to walk through how I use some of these declarative constructions. I won't get into the scary details of how to make declarative constructions in Perl (at least, not in this post).

OokOok themes use a template system like that found in the Radiant CMS: markup with embedded XML-like tags. Tag libraries define these tags, just as a class defines methods. Right now, there are four tags in the core library: pull in a snippet, a page part, and conditionally include content if a page part is or is not present.

Using the power of MooseX::Method::Signatures and some other magic, this looks something like the following:

That's the skeleton of the library. All of the metadata needed to know if we escape the results of the tag before inserting it into the document (e.g., whether it does anything with embedded content) and the allowed attributes (and their types) are there. How it manages to sling all this data around behind the scenes doesn't matter. If that changes, I don't have to touch the tag libraries.

A layout might have something like the following:

The 'r' prefix is automatically associated with the core tag library for now. The CSS classes are from the 960 grid.

The other types of classes aren't as dramatic in how they use declarative forms. For example, here's how I define the board resource:

I've left out the methods that manage authorization, but the above class is enough to define the "board" REST resource. OokOok defines REST resources separately from the tables in the relational database because some resources hide the complexity of versioning and editions from the REST api. A resource may change over time, but we remember all the past versions and can replay them at any time. They just aren't available for managing through the REST api.

Unlike the tag library, we haven't added any new Perl keywords beyond the class declaration ("resource"). Things like "method" are from the MooseX::Declare class. The ones such as "prop" and "has_many" that look like keywords are really functions imported into the package's namespace at compile time (note that their invocation requires a semicolon at the end while "method" and "element" don't). Moose is kind enough to take them out when we finish defining the class so they don't pollute the class's namespace at runtime.

So there you have it. Perl with a modern twist, hiding a lot of the dirty details behind the scenes so you don't have to worry about them if all you're working on is the relationships within the data.