The Exception That Rather Proves the Rule
I had really wanted to stay out of the recent commentary on CGI. I really did. I was going to be able to until a recent article was published in which the authors try to step in on the side of CGI. I believe the authors to be talented perl developers posting in good faith, but the result really pushed me to reply. The application developed as a case for CGI and preventing “overkill” is a perfect example of why a framework is needed.
The Plack App
First of all, although the authors initially signify that they feel that frameworks are overkill, they do in fact quite quickly reach for one. Plack is the reference implementation of a micro framework build on the PSGI standard. It isn’t the lack of a framework, it is the lack of a full framework, by design. So while the authors seem to be saying CGI.pm is bad (at least we agree on that!) and CGI the protocol is good they neither use the protocol directly nor avoid using a framework by say using PSGI directly.
Next they proceed to develop their application, leaving hooks all over the place for testing (and yes testing is good) but the result is almost a new micro framework on top of a micro framework (Plack). Classes for configuration, templates in configuration so they can be overloaded for easier testing, a home rolled logger. BTW they are only classes in that they provide methods, but notice that all of them are class methods, you don’t instantiate this. The result is surprisingly hard to read for such a small app and one that is intended to convey the simplicity of small when small is all that is needed.
Then we get to the footnote. The authors quite quickly noticed that their home rolled framework doesn’t handle utf8 parameters correctly. They had to add more code to properly handle it.
In looking at their code, I also noticed that because they don’t handle exceptions, their own exception thrown if the response isn’t a JSON object would result in no response being sent to the client. A simple oversight I’m sure. They also don’t seem to have a landing page with the form, which likely means that it is in a static directory that they didn’t bundle, but it means that I don’t see it and it has no tests.
A Mojolicious Alternative
Now I’m on the Mojolicious core team, so I think its probably no surprise that in working out a response I reached for Mojo. I even made a Lite app rather than compare apples to apples and make a fully OO “full app” because once you strip out most of their “framework”, you really don’t need it. That said I believe that most of what I’ll write following this could be applied to any modern framework like Dancer(2) or Web::Simple or what have you.
I didn’t time it, but given the lightness of dependencies, I highly suspect that Mojo installs more quickly than did the dependencies of the presented application. Dancer probably is comparable to the presented application. Catalyst … well, ok, Plack is probably better at that consideration. Mojolicious apps can natively run as CGI. PSGI apps like Dancer can be deployed as CGI as well. So for all the fuss over ease of deployment, I don’t see much benefit for the presented application over alternatives.
Anyway, my alternative implementation is on my Github at https://github.com/jberger/slack_invite. Given the head start of cribbing from their app and owing to a lot of experience I was able to write this replacement and tests in about an hour. Without that it probably wouldn’t have been too much more than that amount of time plus the time to figure out how to interact with slack.
The biggest feeling I have looking at the result is how much easier it is to read. There’s a logger and a user agent available. Exceptions are handled natively (I just replaced the default template) as is UTF-8, JSON and rendering a response with headers appropriate to the response type.
One thing Mojo does give me over other frameworks is a testing framework and especially the ability to inject a mock service to replace slack. It lets me use CSS selectors to test the rendered responses, even the initial form. Note that you can use Test::Mojo and/or Mojo::UserAgent in your non-Mojo applications too if you’d like.
Again I want to stress that I’m not trying to attack the authors of this article. In fact I applaud them for showing code that they use and sticking up for technologies that they believe in. That said I think this article, rather than making the case they intend in fact makes the opposite case. Even when you want to do something small and build a webapp that will be used infrequently, an application written in a proper framework is still the way to go.