[dancer-users] Advent 2015, medium-scale Dancer, part 1: Perl Modules
Warren Young
wyml at etr-usa.com
Tue Oct 27 00:18:14 GMT 2015
I’m going to post the article parts here as I finish the first draft of each, for public comment. I’ll do a polishing pass or two later, before these go up on the official site.
This first part has an introduction section that won’t be repeated in later parts, because the parts are intended to be hyperlinked together.
You might want to copy this text into a GUI Markdown editor, so the markup doesn’t distract you from the content. If you don’t have one, try StackEdit:
https://stackedit.io/
It’s a modern online web app for editing and viewing Markdown text.
Getting Beyond Small-Scale in Dancer Application Design
========
When you generate a Dancer app with `dancer2 -a App`, you get a very nicely structured and useful starting point. As long as your app remains fairly small, you can work with this structure as-is clear through to completion. In that sense, the generated app is production-ready.
The problem comes when you start getting to thousands of lines of Perl code, dozens of view files, and hundreds of routes, stretching the stock app design beyond its natural limits. This series of articles gives you one way to extend beyond this base.
I say "one way" because Dancer is a policy-free web application framework. That means it purposely does not make whole classes of design decisions for you. It is up to you to use the toolset Dancer provides as you see fit.
The design presented here is working quite well for us, so we think it is worthy of emulation, but we do not expect that it will for for all medium-scale web applications. Think of it more as a collection of design ideas, rather than a prescription of the One True Way to design a Dancer application.
Part 1: Perl Modules
---------
If you say `dancer2 -a App` at the command line, you get a few dozen files, only one of which is interesting for the purposes of this article.
We're setting `bin/app.psgi` and `public/dispatch.*` aside as "uninteresting" here because we recommend that you leave these files as-is. None of your app-specific Perl code should go in these files.
We're also ignoring `Makefile.PL`, since that isn't part of the app proper.
That only leaves `lib/App.pm`. For small-scale apps, simply piling all of your Dancer-related app code into this file is just fine. Up to about one or two thousand lines of code, you can just use it as-is, for the same reason that a thousand-line monolithic Perl script is fine in other contexts, too.
One of the nicest things about Dancer is that the `App/lib` directory is automatically added to the Perl module path. That leads to an obvious solution to the problem of too much code in a single file: break it out into other `*.pm` files in the `lib` directory. But how, exactly?
I recommend following the example of CPAN, with a structure like the following:
lib/App.pm # your app's main module
lib/App/MajorFeature.pm # implementation of a major app feature
lib/App/OtherFeature.pm # as many feature impl files as you need
lib/App/API.pm # if your app has a REST API, put it here
lib/App/Const.pm # maybe you have some app-wide constants
lib/App/Utility.pm # every big app has a "junk drawer" module
Then in `lib/App.pm`, you `use` all of these modules:
use App::MajorFeature;
use App::OtherFeature;
use App::API;
use App::Const;
use App::Utility;
How you design these modules is up to you. Standard [good Perl application design principles](http://stackoverflow.com/questions/410359/how-can-i-learn-to-write-well-structured-programs-in-perl) apply.
There is one Dancer2-specific thing to beware of here, though: you must [set the `appname` property on the sub-modules](http://advent.perldancer.org/2014/10). If you don't, each sub-module will be considered a separate Dancer2 application, which puts unwanted barriers between the modules.
(Dancer1 didn't have this restriction, because it was all just one global app.)
The only Perl code remaining in `lib/App.pm` will be application initialization code, to be run once during app startup.
(This, by the way, is why we don't need to modify `bin/app.psgi`: since it pretty much just loads Dancer and then calls `lib/App.pm`, there is no point to splitting app initialization code across the two files. Let `bin/app.psgi` remain a tiny little glue file to make PSGI happy.)
Having done all this, about all that's left in `lib/App.pm` are the route definitions, which are the subject of the next article in this series.
More information about the dancer-users
mailing list