[Catalyst] Random thoughts on helper class generation

neil.lunn neil at mylunn.id.au
Sat Jan 25 02:40:04 GMT 2014


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




More information about the Catalyst mailing list