[Catalyst] Random thoughts on helper class generation

neil.lunn neil at mylunn.id.au
Mon Jan 27 06:39:36 GMT 2014


On 27/01/2014 1:27 PM, John Napiorkowski wrote:
> Neil,
>
> I know the problem we have here, but honestly I think the solution is going to be more about having less stuff in Catalyst.pm rather than more...
Hi John,

Actually probably missed something in my intended context in the course 
of the rant.
Couldn't agree more with that statement, truly "less is more" and I 
wasn't putting a shout out to either change 'Catalyst::Helper' or 
otherwise bloat things in 'Catalyst Core'. So I think we can agree that 
it is better to pull things out and delegate to more "generic" "add-in's".

I have seen in some reading terms and statements such as "monolithic 
catalyst application ...", which is sadly a sad misnomer and seems more 
of an indictment on the development model of the authors than an actual 
problem of Catalyst itself.

> That said, it doesn't help today much :)  Feel free to try a plugin and see what people think.  Is a good way to shakeout new ideas.
So largely a position on "how many people are generally cargo culting 
the catalyst helper default files", which probably would have been a 
better title. And otherwise trying to get a feel for what other people 
were doing as typical, "App", "Controller", "View", "Model" setups.

As for the code, that was my way of saying "here's one other way of 
doing it, what's yours?"

If anything, the only critique here regarding the helper templates is 
that new inductees are likely to come on board and just so things as 
they are in the manual, without much thought to what is actually 
happening. Hence the reference to "getting logging set up under 
ConfigLoader", and so we show another approach. But not sure exactly 
what to do about making people think, and think differently, yet.

> John
>
> On Friday, January 24, 2014 8:42 PM, neil.lunn <neil at mylunn.id.au> wrote:
> On 25/01/2014 10:58 AM, neil.lunn wrote:
>> Hi all,
>>
>> Was just thinking through setting up various project minting files and
>> got to looking at the default Catalyst app layout from the helper.
>> Specifically I wondered how much the defaults were just being cargo
>> culted, and specifically addressing my dislike for overuse of inline
>> __PACKAGE__ calls when we have Moose and BUILD available. So random
>> musings below:
>>
> Oops. Big fail. Forgot the most important bit. See edit
>> Here's a sensible base class for the App context:
>>
>> package Catalyst::BaseClass;
>> use Moose;
>> use namespace::autoclean;
>>
>> use Catalyst::Runtime 5.80;
>> use Catalyst qw/ PluginLoader /;  # Should be all we need
>>
>> extends 'Catalyst';
>>
>> our $VERSION = '0.01';
>>
>> sub hook_config {
>>     my $self = shift;
>>     my $class = ref($self);
>>
>>     # Set some basic defaults
>>     return {
>>       name => $class,
>>       enable_catalyst_header => 1,  # Send X-Catalyst header
>>     };
>> }
>>
>> sub hook_logger {
>>     # Do nothing by default. Setup will take care of it.
>> }
>>
>> sub BUILD {
>>     my $self = shift;
>>     my $class = ref($self);
>>
>        unless ( $self->setup_finished ) {
>>     # Setup Config
>>     $self->config(
>>       %{ $self->hook_config }
>>     );
>>
>>     # Place a hook to hang a logger on before setup is called
>>     $self->hook_logger();
>>
>>     $class->setup();
>          }
>> }
>>
>> As you can see by the "hook" methods, this was "take 2"  where I was
>> abstracting my personal "cause" from the general base class. By
>> placing the hooks in you can abstract in your application, as in:
>>
>> package YourApp::Web;
>> use Moose;
>> use namespace::autoclean;
>>
>> extends 'Catalyst::BaseClass';
>>
>> our $VERSION = '0.01';
>>
>> our $load_class = \&Plack::Util::load_class;
>>
>> around 'hook_config' => sub {
>>     my $orig = shift;
>>     my $self = shift;
>>     my $class = ref($self);
>>     my $basename = $class;
>>     $basename =~ s/::.+//g;
>>
>>     use Hash::Merge qw/merge/;
>>
>>     # Setup Config
>>     my $configclass = $load_class->( "${basename}::Config" );
>>     return merge( $self->$orig, $configclass->config || {} );
>>
>> };
>>
>> override 'hook_logger' => sub {
>>     my $self = shift;
>>
>>     # Optional logger from class
>>     my $logger = $self->config->{Logger};
>>     if ( defined $logger ) {
>>       die "Config Logger requires a Class key"
>>         unless $logger->{Class};
>>
>>       my $logclass = $load_class->( $logger->{Class} );
>>       $self->log( $logclass->new( @{ $logger->{Config} || [] } ) );
>>
>>       $self->log->debug( qq/Initialized logger: "$logclass"/ );
>>
>>     }
>>
>> };
>>
>> Now, realistically even the *second* and extended implementation is
>> still notably generic and *for me* this is even enough to place as a
>> *base class* to every application as this is how I will lay things
>> out. Plack::Util seems to be a fair assumption to be loaded as the end
>> result is a PSGI app, and Plack::Runner is going to pull this in. For
>> the nosy, the Logger class in this case is a mere wrapper around
>> Log::Log4perl in this case, and would only get the logger instance if
>> it had already been initialized. You can (and I do) set up Plack
>> middleware to do the same thing, making the same logger available to
>> other PSGI parts that might be used in your application, all without
>> needing to wrap context to get at the logger, or explicitly call
>> Log::Log4pperl::get_logger as we might just want to change that to a
>> different logger at some stage.
>>
>> So general thoughts are:
>> 1. Have a config class that is external to Catalyst logic. You can use
>> it elsewhere without hassle.
>> 2. Have a hook to hang that config on and get it early; because
>> 3. Hang a logger on a hook before 'setup' is called so you can get the
>> startup logging on debug
>> 4. Pull in the plugins from Config so there isn't a need to keep
>> modifying that code in the context class for every app
>>
>> Also minimising the selection of Plugins. I do try to keep this to
>> session and auth stuff for convenience, and again have these as just
>> thin layers over Plack Middleware. Other things can be delegated to
>> role applicator stuff, which I haven't typed in here.
>>
>> Anyone else have thoughts? Alternate favourite methods for layout?
>>
>>
>>
>>
>> ---
>> This email is free from viruses and malware because avast! Antivirus
>> protection is active.
>> http://www.avast.com
>>
>>
>> _______________________________________________
>> List: Catalyst at lists.scsys.co.uk
>> Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
>> Searchable archive:
>> http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
>> Dev site: http://dev.catalyst.perl.org/
>
>
> ---
> This email is free from viruses and malware because avast! Antivirus protection is active.
> http://www.avast.com
>
>
> _______________________________________________
> List: Catalyst at lists.scsys.co.uk
> Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
> Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
> Dev site: http://dev.catalyst.perl.org/
>
>
> _______________________________________________
> List: Catalyst at lists.scsys.co.uk
> Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
> Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
> Dev site: http://dev.catalyst.perl.org/


---
This email is free from viruses and malware because avast! Antivirus protection is active.
http://www.avast.com




More information about the Catalyst mailing list