If you are familiar with Catalyst the above probably doesn't seem so
surprising to you. If we assume the example controller is lifted from a
'classic' style application (with a ::Root controller that has a base action
from which everything chains off, and an end action which inherits from
Catalyst::Action::RenderView) we can see that the following
HTTP requests would be handled:

However for people new to the framework, there is often a lot of confusion
regarding the difference between an action and a regular controller method,
and when to use which. Also, it is not always immediately evident what is
what when opening a Catalyst::Controller based class for the first time.
And compared to some of the newer web frameworks floating around CPAN, it
might seem like the syntax for Catalyst::Controllers is a bit, "over the
hill".

More Modern Controllers?

Catalyst developers, in our quest to come with a more modern syntax that
retains the overall power and flexibility, and hopefully solves some of the
bigger problems with classic contollers, have experimented broadly. You can
review CPAN and spot ideas like CatalystX::Declare or
CatalystX::Controller::Sugar. In these cases, the authors have tried
replacing the 'Plain old class' syntax with a type of domain specific language
that is designed to better express the type of logic one needs to build good
controllers.

Although the syntax is certainly shiny, the downside is that we no longer
can leverage all our existing knowledge about how to properly model straight
forward classes using standard practices (Like inheritance, roles and so
forth.) We have to work within the DSL. Additionally those experiments are
internally documented but are not part of the broader documentation ecosystem.

Mentioning these possible downsides, I am not intending to disparge the authors'
efforts, but merely to point out upsides and downsides. Each project should
seriously consider the value and demerits of all the possible approaches and
choose something that makes sense for the team and business need.

In order to split the difference between trying to introduce shiny new syntax
and yet keep things similar enough to the vast amounts of Catalyst documentation
as to be immediately recognizable and understandable, I've introduced
CatalystX::Syntax::Action on CPAN.

CatalystX::Syntax::Action sticks with the idea that a Controller is just
a specialized class, so it doesn't really add a new domain specific language.
What it does is add a bit of Devel::Declare based magic to create a new Perl
keyword action which just encapsulates some of the basic boilerplate that
goes into your Catalyst Controllers. It also plays nice with the syntax
namespace and can be a good part of that ecosystem as well. Hopefully someone
that did the Catalyst tutorial and read the book would be able to immediately
understand this syntax, and would not require much additional study. Let's
rewrite the above controller using CatalystX::Syntax::Action and some other
members of the syntax ecosystem:

There's not a big difference here, hopefully if you understood the 'classic'
controller, this change would not confuse you. Let's review the changes:

use syntax 'method', 'catalyst_action';

When you installed CatalystX::Syntax::Action (via your Makefile.PL
hopefully) we added support for the catalyst_action argument to the
syntax pragma. This is a pragma for managing adding syntax features to
Perl. In this case we also are using Syntax::Feature::Method, which adds a
method argument as well. You can review the Syntax::Feature namespace on
CPAN for more examples of pluggable syntax you can leverage in your code.

The action and method keywords basically wrap the sub keyword, adding
two features. First of all action will automatically expose two lexically
scoped variables to your method block, $self and $ctx. These exactly map
to my ($self, $c) = @_ in the classic controller. We use $ctx over $c
in order to reduce confusion and to canonicalize evolving practices within the
Catalyst community.

Secondly, it lets you specify arguments in the method prototype, which may seem
nicer to programmers coming to Perl and Catalyst from other languages. It
also leads to a bit less boilerplate code since you don't have to shift or
map from @_ to get lexical variable into your method scope.

In all other cases methods that are declared with the action keyword function
identically to those declare with a sub.

For how the method keyword works, you should look at Syntax::Feature::Method
but the one sentence summary is that it is just like action but of course
we don't create a lexically scoped $ctx since you are not expecting one.

So that is all there is, basically just like classic controllers, but a bit
less boilerplate in the method blocks, and some support for method prototypes
that hopefully will be attractive to programmers used to having those in other
programming languges. I also find that the keywork action really jumps out
at me in my source code, and makes it easier to immediate distinguish actions
from regular methods.

Summary

Authors in the Catalyst ecosystem continue to experiment with possible
approaches for advanced, new techniques for building concise Controllers that
are both easy to understand and do what programmers need with a minimum of
boilerplate code. Additionally, we want to consider how we can keep well
synchronized with the broader ecosystem of code on CPAN and with evolving
best practices for modeling objects. One of the great things about Catalyst
is how well it lives in the larger Perl world. It tries hard to not introduce
too much new syntax or practices, but instead wishes to say, "This is how one
builds great Perl software, and we are going to be a good member of that
community."

That is certainly something we'd wish to keep! Happy Holidays to all!

AUTHOR

John Napiorkowski <jjnapiork@cpan.org> or jnap on IRC.

Thanks to Shutterstock (http://www.shutterstock.com/jobs.mhtml) for giving me
a bit of time to review and craft this advent article.