[ABE.pm] what rjbs is up to

Ricardo SIGNES rjbs-perl-abe at lists.manxome.org
Fri Dec 15 17:03:54 PST 2006


Programmery People:

How's it going?  I am stuck on a bus and going insane.  So far it's taken us
2.25 hours to get from Philadelphia to Quakertown, but I think things are going
to speed up now.

Anyway, I thought I'd use this time to finally talk about some of the stuff
I've been up to.  Some of it has been fun.

I think I already talked, at the bar, about some of the memory optimizing I've
been doing in Perl Email Project code.  It's nice to pick the low-hanging
fruit, now and then.  It's especially nice when the fruit is hanging low from a
really commonly-used module.  It would be neat if there were some way to see
what kind of performance impact one's code changes has on every install in the
world, but I think that's what they call "spyware."

  http://use.perl.org/~rjbs/journal/31737
  http://use.perl.org/~rjbs/journal/31749

Today I wrote up another bizarre and hateful problem that came out of that
process.  Basically it goes like this:  calling UNIVERASL::can or
UNIVERSAL::isa as functions sucks.  If you call them on an object with special
behavior for isa or can, it's skipped.  Instead, you should call them as a
method, and use eval{} to avoid dying.  I only recently discovered the
ridiculous side effect in older perls.  If you ever pass in a gigantic string,
especially with certain characteristics, you can bloat your memory usage up in
insane, hateful ways.

  http://use.perl.org/~rjbs/journal/31922

A very simple-to-generate long string can exhaust memory when used as an
invocant under perl-5.6, with no problem.  That is, I can exhaust your several
gigs of RAM with a string of a meg or so and one call to isa.  Ack!

I also had some fun tweaking Sub::Exporter, but I think you're all sick of
hearing me talk about how much I love my favorite module.  If my modules were
my children, all the others would gang up and smother Sub::Exporter out of
jealousy.  Sub::Exporter would never do anything like that.  Why can't my other
chil^Wmodules be more like Sub::Exporter?

  http://use.perl.org/~rjbs/journal/31812

Then I played with those improvements to produce something I've had sitting on
a back burner forever.  It's a mixin that provides places to stick ... stuff.

A mixin is like a little shard of a class that you mix into your class to give
it extra magical powers.  It's analagous to the way that a module of routines
is mixed into the core language to give the language extra magical powers.
When you use, say, Math::Trig, it's like you're mixing trig routines right into
the language.  If you used Mixin::Serialize (which doesn't exist), you'd be
mixing trig /methods/ right into your /class/.

Sub::Exporter is really good for making mixins... but I won't get into that.

Anyway, I hate writing code.  I prefer to sort of dangle a string into a glass
that's supersaturated with code solute and then watching the code grow on the
glass while I enjoy a beer.  There are lots of tools to eliminate writing
repetitive code.  A popular one is Class::Accessor, which installs methods into
your class for accessing the guts of your object, assuming your object is a
blessed hash reference.  There's also Class::MethodMaker, Class::Meta, Moose,
and more.

What I wanted was a simple way to add more datapoints to an object without
having to worry about what the object was -- I wanted it to work whether it was
a hashref, a coderef, or any other nonsense.  Further, I wanted to be able to
change the way the datapoints were stored, too.  Sometimes I'd just want them
in memory, other times in different kinds of databases... and sometimes I'd
have to use databases that already existed.  Finally, I wanted to be able to
store an arbitrary number of named fields for any object.  I didn't want to
have to say, up front, "yeah, so this class is going to have a flavor field, a
moonphase field, and a rsPLSchottky field."

So, this was actually fairly straightforward, with a couple bits of
abstraction.  I released this distribution, last week:

  http://search.cpan.org/dist/Mixin-ExtraFields/

It lets you write code like this:

  package Corporate::WorkOrder;

  use Mixin::ExtraFields -fields => {
    id      => 'workorder_id',
    moniker => 'note',
    driver  => 'HashGuts',
  };

and now your WorkOrder objects can be dealt with like so:

  $order->set_note(moonphase => 'waning gibbous');

The "driver" sets up how things are stored, and you can change them in and out
without anything else having to change.  Also, since you can give different
monikers, you can have a bunch of these extra sets of fields, each using a
unique storage driver and/or location.

This has been really convenient for cleaning up several similar (but, if I may
say so, inferior) implementations of this kind of concept at work.  In fact, as
soon as I replaced one or two, I found that it had become so easy to change how
they worked that I was able to change a line here or there and greatly simplify
some code.

The other fun thing is that Mixin::ExtraFields is a class that mixes things in
out of ingredients.  It doesn't mix itself in like many mixins do.  That means
it can be subclassed to mix things differently.

I've already written a few subclasses, like one that mixes in a Data::Hive, so
you can say this:

  $t_shirt->notes->quality->inspected_by->SET("Number 8");

Just by using "Mixin::ExtraFields::Hive" insead of the normal class.  There's
also a ::Param subclass, which gives you a param method like those found on CGI
and CGI::Application and Catalyst and lots of other webby things.

I need to write some more drivers.  I've written one for our proprietary ORML
(like Class::DBI) at work, but that doesn't help people outside of the VPN.  I
might write one for Class::DBI or DBIx::Class.  I've also thought about writing
one like HashGuts, but using inside-out techniques.

I have no idea if this scratches anyone's itch but my own, but it was a lot of
fun, and I hope that I can popularize, at least a little, the Mixin:: namespace
and construction technique.

Well, we're finally coming down 378 into Bethlehem.  It's 20:02, and I'm
famished.  I'm going to get some dinner and go home.

-- 
rjbs


More information about the ABE-pm mailing list