I've spent the last 2 days staring at as many CGI / webapp frameworks as I could:
And basically all of them seem to miss what we see merlyn speaks of in his DESCRIPTION to CGI::Prototype -being a fan of clean MVC designs, the classes become the controllers ... and CGI::Prototype a sort of "archetypal" controller.Now, from this point, we are going to look at the CGI::Prototype controller. Then I will discuss the power of such a controller theoretically. Then I will give a concrete example of why it is important that controllers be in a hierarchy of classes.
$next_page->render;
sub activate { my $self = shift; eval { $self->prototype_enter; $self->app_enter; my $this_page = $self->dispatch; $this_page->control_enter; $this_page->respond_enter; my $next_page = $this_page->respond; $this_page->respond_leave; if ($this_page ne $next_page) { $this_page->control_leave; $next_page->control_enter; } $next_page->render_enter; $next_page->render; $next_page->render_leave; $next_page->control_leave; $self->app_leave; $self->prototype_leave; }; $self->error($@) if $@; # failed something, go to safe mode }
I said to focus on $next_page->render because that is what I will demonstrate from a practical perspective. But as you can see any aspect of the HTTP response cycle can be handled in an object-oriented fashion.
I stared in utter confusion at every single framework above. I looked at Catalyst subroutines, Jifty actions, Mason components, and so on. And in each case, they seemed to miss the magick of merlyn's methodic approach to web application control.
With CGI::Prototype, it is very easy to create a "family" of actions and have them derive behavior from each other.
But enough talk. Let me provide a simple concrete example.
which calls the engine method:->render
And this page is quite simple. It finds the "template file" for logging in. hen it removes all the data validation HTML from it.package Gimble::Page::Login::Base; use base qw(Gimble::Page::Base); sub engine { my ($self,$tree) = @_; $self->snip_validate($tree); $tree } sub template { require html::login; html::login->new } 1;
Of course there are other logic tasks in a CGI application - dispatch, authentication, authorization, to name a few. But having had experience with many CGI / webapp frameworks, I think merlyn describes exactly how CGI::Prototype fits into the picture perfectly:
Create a CGI application by subclassingand I think it has the best setup for pluggable expansion into these other tasks as well.
Of course, it needs a Moose rewrite...
Now what happened? I had written a few CGI apps using CGI::Application. Then they turned the k0der loose to do his own. And guess what? He stuck everything for a particular CGI action in each subroutine. Now we have a 300k .pm file.
Now, refactoring this is going to lead to merge conflicts. If he had been forced into the CGI::Prototype mode of "creating an application by subclassing" he would have had to partition his spaghetti brainfuck into separate modules and we could have a developer per module and no merge conflicts to sort out.
CGI::Application was a great step away from the HTML::Mason / Embperl approach to web application flow control. In my opinion, the next improved step is CGI::Prototype, having done my best to understand the merits of other CGI / web app frameworks, be they big or small, popular or unpopular!
|
---|