What I expect from a Web Framework

Spoiler: Pain and suffering.

I learned to hate Web Frameworks. Web Frameworks are dead. Or should be. So this post is actually about...

What I expect from an App Framework

Earlier this week, Gabor asked, what the three most important things missing from Perl6 are that keep us from writing a web application in Perl 6.

You can find my original, short answer here, but Gabor asked for some clarifications, which I will now try to provide here.

So, what do I expect from an Web/App Framework?

The Web Framework Is Dead

The main problem with Web Frameworks is the "Web"-part.

You either have a good web framework (Catalyst, Dancer) which makes it hard to reuse your code in non-web-contexts (and there are a lot of those: cronjobs, tests, fixup scripts, daemons, importer & exporter, ...); or you have a "closed system" like Mojolicous or Ruby on Rails, which tend to include everything (i.e. they come with their own email-system, cron-replacement, event loop, ...) but sort of drift away from the main language and generate their own ecosystem / walled garden.

A Web Framework wants the Web-part to be the King of your project. But I want the problem I'm trying to solve to be the King of my project.

Superglue is the new Framework

I want a framework that makes it easy to stitch various things together. I found the concept of Dependency Injection and its Perl implementation Bread::Board0 fitting my needs perfectly.

All the proper code (aka Business Logic) lives in Fat Models. Each Model is a plain framework-less class that maybe depends on some things (i.e. instances of other classes). Those instances are injected into the class when the class is initiated.1

If the app needs a Web interface, I set up some Slim Controllers and a router. The router explicitly2 maps URLs to classes and methods (aka actions). Each action just has to unpack the params and/or JSON payload, pass it on the the Model, and handle the response. If it's an JSON-API this means to just serialize the data structure returned by the Model. If it's an old-school HTML app, the controller passes the data on the a Stupid View for rendering.

But if the same interaction with the data has to happen via e.g. a commandline script, I just need to set up a small wrapper that unpacks the commandline args, passes them to the Model and handles the response (by printing it to the terminal, for example).

This is even more true for unit tests, where I do not want to fork a webserver (making it impossible to use transactions to keep the test-DB clean) or mock the whole framework environment just to check if $model->foo(42); returns the right data.

My Stack

After doing mostly webstuff for nearly 20 years (working through all the classics like CGI3, mod_perl4, homegrown frameworks with funny names5, Catalyst, Plack/PSGI), I am currently happy with:

PSGI, because it allows me to have app/framework-ignorant Middlewares that I can reuse no matter what tool I choose to implement the controllers.

OX, because it allows me to easily map URIs to method calls, and does not force any "helpful magic" on me.

Bread::Board, because it provides me with one location where I can define all the parts needed by my app (which is not only a web app!), and allows me to pick the parts I need for a given task with little fuzz.

DBIx::Class, because life is too short to concatenate strings and vars to get simple SQL queries.7


So are those the things I'm missing from Perl 6?

Honestly, I have no clue.

Because I currently enjoy hacking frameworkless code in Perl 5 more than getting to know the Perl 6 ecosystem. Which is a shame, because a part of me wants to start using Perl 6 a lot.

If somebody could point me to Perl 6 solutions to the core tools of my stack, I might actually get around to finally get my feet wet. If I first have to implement them, it might take a while longer...

Sponsored by the current heat wave in Vienna which makes it impossible to sleep at night, so I might just as well write this post.


0 An unfortunate name, as only a very small subset of humanity knows what the inspiration was. I was very confused...

1 Do not use lazy loading for this. You will be kicked by a Moose if you do!

2 So you can grep for URLs in your source code, something that's quite impossible when using Catalyst.

3 which now is dead, BTW

4 deadish, but still a very good piece of tech. Wow, the website still uses the "design" we implemented in ~2001

5 never should have been alive...

4 Except when it's not, see my upcoming talk The Power of Raw SQL at The Perl Conference in Amsterdam