Re: Annouce: DBIx::Class, a.k.a "taking the easy way out"

[prev] [thread] [next] [Date index for 2005/07/26]

From: Matt S Trout
Subject: Re: Annouce: DBIx::Class, a.k.a "taking the easy way out"
Date: 16:59 on 26 Jul 2005
On Mon, Jul 25, 2005 at 05:26:11PM -0700, Michael G Schwern wrote:
> On Tue, Jul 26, 2005 at 12:55:40AM +0100, Matt S Trout wrote:
> > > *RATTLING CHAINS* Learn from my fate!
> > 
> > The following script lets me analyze the chain of whatever method I need to
> > relatively easily

Before I start: I'm going to make specific cases why specific MI problems
hopefully won't trouble me overly. I'm aware there's a lot more to this
whole minefield than that, but I'm willing to chance it to see if it works
because this architecture seems to me like it'll end up sucking less than
the alternatives for what I want to do with it. ICBW, YMMV, etc. - but I
still think it's worth giving it a go to find out.

> You're missing the point about what's wrong with mulitple inheritance.
> Its not just about the ambiguity of what method will be called.  There's the
> diamond inheritance problem.  There's the conceptual issue of inheriting
> unrelated behaviors from N different subclasses, all which have to be
> careful they don't share any public or protected method names.  There's 
> accidental inheritance, inheriting a method or behavior you didn't intend on.
> import() is a common example.  AUTOLOAD() from DynaLoader (and it from
> AutoLoader).

Diamond inheritance is potentially troubling; I'm probably going to make all
my NEXT calls NEXT::DISTINCT calls instead to try and ameliorate this, but
you're right, it can still be a problem.

However, provided everything is using NEXT, none of the DBIx::Class internals
and plugins will need to inheirt from other DBIx::Class stuff to get their
job done; they'll simply need the front-end class to have inherited from the
appropriate place to have the API available - which nextalyzer.pl can
check for me quite easily.

> CDBI has the problem of inheriting set() and get() from
> Class::Accessor leaving no one else able to use it in conjunction with CDBI.

That drives me insane - I get round it by the use of DBIx::Class::AccessorGroup
which allows me to create accessors bound to groups - so column accessors
call get/set_column, hasa accessors (in the emulation layer, dunno whether I'll
keep it yet, mentioned as example only) use get/set_has_a etc. etc.

> There's the brittleness of relying on inheritance order.

Yes. Yes there is. Apart from having something that can check for obvious
stupidity caused by your inheritance order, there's not much I can do about
it apart from tell people "Be Careful!".
 
> But there's the static nature of using MI to gain behavior rather than 
> delegation.  Given the discussion about plug-ins this bears mentioning.
> 
> If I want to override, say, your SQL abstraction behavior... well I can't.
> You've hard coded this behavior via inheritance.  If you were, instead, to
> delegate this behavior to an SQL abstraction object and call methods on that
> object you now allow anyone to write an SQL abstraction class with a similar
> interface as yours and plop their object in place of yours.  Its flexible.
> It avoids having to hack in a plug-in architecture later.

Now I think you're missing the point :)

DBIx::Class::Core contains

use base qw/DBIx::Class::Relationship
            DBIx::Class::SQL::OrderBy
            DBIx::Class::SQL::Abstract
            DBIx::Class::PK
            DBIx::Class::Table
            DBIx::Class::SQL
            DBIx::Class::DB
            DBIx::Class::AccessorGroup/;

It isn't really a module in its own right, just a "standard recipe" for
composing a set of DBIx::Class components for use in an application. If
you want to do something different, all you have to provide is a class
called My::DBIC::SQL::Abstract which includes a suitable sub _cond_resolve,
and then create your own recipe -

package My::DBIx::Class::Core;

use base qw/DBIx::Class::Relationship
            My::DBIC::SQL::Abstract
            DBIx::Class::PK
            DBIx::Class::Table
            DBIx::Class::SQL
            DBIx::Class::DB
            DBIx::Class::AccessorGroup/;

(note I've removed the OrderBy plugin as well because SQL::Abstract handles
it)

Whether you consider this "recipe" style good or not is a matter of taste.
I like blurring the boundaries between core and plugin, because I think
the difference between the two should, in the ideal system, be semantic
only. Note that this refers to code, not API - that's a whole different can
of worms.

> It allows you to more easily use somebody else's SQL abstraction module 
> (like SQL::Abstract from which you borrowed code) instead of reinventing the 
> wheel... again.  Part of the problem with Perl's persistance modules is they 
> keep reinventing the same wheels over and over again repeating the same bugs, 
> recoding the same features and needlessly dispursing effort.

If you'd like to plugin SQL::Abstract instead of my code, it should be as
simple as -

sub _cond_resolve {
  my ($self, $cond, $attrs, $join) = @_;
  my $args = ($join ? { cmp => $join } : { });
  my ($sql, @bind) =
    SQL::Abstract->new($args)->where($cond, $attrs->{order_by});
  push(@{$attrs->{bind}, @bind);
  return (wantarray ? ($sql, @bind) : $sql);
}

(not tested)

In fact, my implementation started out being pretty much exactly that; I
only ended up importing the code itself because I required semantic changes
in how it handled bind name and values that I didn't think were suitable for
SQL::Abstract itself; I will at some point get round to chatting to the
author and seeing whether he'd prefer to accept a patch.

        -- 
             Matt S Trout           Website: http://www.shadowcatsystems.co.uk
  Technical Director        E-mail:  mst (at) shadowcatsystems.co.uk
Shadowcat Systems Ltd.

(message missing)

Re: Annouce: DBIx::Class, a.k.a "taking the easy way out"
Matt S Trout 16:59 on 26 Jul 2005

Delegation vs Hooks (was: Annouce: DBIx::Class, a.k.a "taking the easy way out")
=?ISO-8859-1?Q?Ask_Bj=F8rn_Hansen?= 23:27 on 26 Jul 2005

Generated at 16:36 on 28 Jul 2005 by mariachi v0.52