On 5/22/2014 11:01, Josh Chamas wrote:
You know I have not much followed the routing paradigms. To me it seems
that this would be an area I would have solved with a mod_rewrite or a
mod_perl handler, changing up the URL destination on the back end.
Routing is more than just an abstraction between the implementation
level and the presentation to the browser. It forces you to consider
your logical URL structure.
My Apache::ASP code just growed, like Topsy. One page at a time, with
no consideration of the interfaces exposed by the other pages. There
was consistency of design only to the extent that there was code
copying, and then in decreasing fashion with respect to time, as the
cloned pages diverged.
As soon as I started developing a system of routes in the Dancer port, I
realized that I had an API. It was sitting there the whole time, never
identified in the Apache::ASP form, but there it was in the Dancer code,
clear as day. Once I'd formally extracted it, I spent a day redesigning
it the way it should always have been. The correct design popped right
out, obvious as a green sky.
This happens because you have to describe your URL structure to Dancer,
one URL per line. Many fit in a single screen of text, so patterns jump
out at you.
Example in Dancer pseudocode:
get '/' => ...
get '/login' => ...
get '/logout' => ...
prefix '/app' => sub {
get 'page1' => ....
get 'page2' => ....
};
prefix '/api' => sub {
del 'foo/:id' => ...
get 'foo/:id' => ...
post 'foo' => ...
put 'foo' => ...
get 'bar/:id' => ...
...same as foo...
};
The story this route structure tells is clear:
1. First you go to the top level page, which perhaps has a Log In link
or button to send you to the /login page.
2. The /login page creates a session and bounces you to /app when you
log in successfully.
3. There's a button or link somewhere that sends you to /logout, which
destroys your session and sends you back to / or /login.
4. The app does CRUD-y things to "foo" and "bar" objects through
/api/{foo,bar}, creating via PUT, reading via GET, updating via POST,
and deleting via DELETE. GET and DELETE require a record ID to tell the
handler what to operate on, while PUT and POST must be fairly complex in
what they will accept, so that the parameters cannot be marked as
required in the route structure.
It's kind of like that Fred Brooks quote, "Show me your flowcharts and
conceal your tables, and I shall continue to be mystified. Show me your
tables, and I won’t usually need your flowcharts; they’ll be obvious."
I wonder if Apache::ASP were to be made to work
with something like Plack, if it would pick up some routing potential on
the way (or maybe just a Plack way of doing things?)
I don't think so. I believe a minimum-effort Apache::ASP Plack port
would have only one feature relative to Apache::ASP v2, that being web
stack independence. From your perspective, the big difference is that
you have to replace all the mod_perl Apache2::Foo stuff with Plack/PSGI
equivalents.
To get a handle on what routing does for Dancer, say:
$ sudo cpanm Dancer
$ dancer -a foo
This generates a complete, self-contained sample app, suitable for
hacking on directly. That is to say, the file and directory structure
it generates is suitable for production use.
The routing structure is in foo/lib/foo.pm. You also use this file to
define hooks, which are roughly equivalent to global.asa event handlers
in Apache::ASP. Script_OnStart is the same as Dancer's "before" hook,
for example. There is no direct equivalent of Session_OnStart, but you
can build that into the "before" hook, too. The Dancer equivalent to
the Application_* event handlers is foo/bin/app.pl.
If Apache::ASP were to get a routing system, I don't know that you'd
necessarily want to put it in global.asa. It works well for Dancer, but
perhaps another design would make more sense for Apache::ASP, since
global.asa has historical meaning.
Notice, by the way, that foo/lib gets added to @INC by foo/bin/app.pl.
This solves another problem I had with Apache::ASP, which doesn't like
you to define functions and classes in your *.asp files. You end up
creating *.pm files to hold all reused and complicated code. Where then
do you put those *.pm files so that mod_perl can find them?
In my Apache::ASP app, I ended up installing them into the system's
site_perl directory, and then I could never remember the path to those
files when I had to hand-hack one of these files on a production server
to test a problem fix in the field. With Dancer, the *.pm files are
right there next to the rest of the app.
The most problem with Apache::ASP for by now is that it is tied to
mod_perl
with it's module reloading ,memory hogging problems.
Yes, always been a problem, but memory is so cheap! :)
I know you're joking, but RAM on VPSes isn't cheap. 4 GB more RAM in my
colocated box is virtually free. 4 GB of RAM added to my cheap
bare-bones VPS plan adds another $35/mo, or $420/yr, or $2,100 over the
expected lifetime of the server.
There's another advantage of Dancer. By going with a single long-lived
app process instead of forking off Apache children, and by making that
app independent of tubby ol' Apache, we can squeeze our app into much
smaller VPSes and VMs.
In extreme situations, you don't even need a traditional web server.
That "foo" app I had you create above? It contains a perfectly usable
basic web server, listening on port 3000. Run it as root so it can bind
to port 80 instead or port-forward 80 to it, and you've got an entirely
self-contained app.
---------------------------------------------------------------------
To unsubscribe, e-mail: asp-unsubscr...@perl.apache.org
For additional commands, e-mail: asp-h...@perl.apache.org