----- Original Message ----
From: Jonathan Swartz <swa...@pobox.com>
To: moose@perl.org
Sent: Wednesday, February 11, 2009 3:55:50 AM
Subject: advice on wrapping methods from a superclass

CHI (http://search.cpan.org/~jswartz/CHI-0.091/lib/CHI.pm) is a Moose-based 
caching framework. There is a driver superclass (CHI::Driver) and various 
driver subclasses that implement different cache backends (CHI::Driver::File, 
CHI::Driver::Memcached, etc.) Drivers implement standard methods like remove() 
and clear(). e.g Currently, if you call $cache->remove(), it goes directly to 
the driver subclass.

The problem is that there are now legitimate reasons to "wrap" these methods at 
the CHI/Driver.pm superclass level (meaning, do something before and/or after 
the method). For example, I want to add an optional generic size-awareness 
feature (the cache can keep track of its own size), which means that we have to 
adjust size whenever remove() and clear() are called. And I want to log 
remove() calls the way we currently log get() and set().

So one solution is to define remove() and clear() in CHI/Driver.pm, and have 
them call _remove() and _clear() in the driver subclasses.  But this kind of 
change makes me uneasy for several reasons:

* It changes the driver API, i.e. all existing drivers out there have to 
modified. And we might have to change it again as we identify new methods to 
wrap.

* The list of 'normal' versus 'underscore' methods becomes rather arbitrary - 
it's "whatever we've needed to wrap so far".

Moose has before & after modifiers, but can they be defined in the superclass 
and affect the subclass??

I guess CHI.pm could use a wrapping module, like Sub::Prepend or Hook::LexWrap, 
on any driver class the first time it is used, e.g. the first time someone says

    CHI->new(driver => 'File')

we wrap the appropriate File methods. But this feels hacky - these tools seem 
like a way to modify someone else's module, not as a standard part of your own 
class.

Advice appreciated!

Thanks
Jon

I may not be grasping the exact problem, but I wonder if CHI::Driver shouldn't 
be a role instead.  Then you could require a method and add a wrapper as well.  
Lately I've been thinking unless the class is going to be instantiated it 
should be a role.  I'm not so down on base classes anymore.  Not sure if that 
helps. 

John


      

Reply via email to