OO Architecture redux

[email protected] (Tim Bunce) Thu, 29 Sep 2005 19:35:26 +0100
Newsgroups perl.dbi2.dev
Message-ID <[email protected]>
Okay, so where have we got to...

Subclassing:

 - Useful for adding/changing behaviour in a driver-indepandant way

 - Hard (bordering on impossible) to use multiple subclasses at once.

More Classes (Roles):

 - "The DBI" will be less of a single entity than it was before.
   So "subclassing the DBI" will become less meaningful.
   It'll be "subclassing the DBI <foo>" where foo can be
   connections, statements, logging, driver management etc. etc.

Roles:

 - Perl6 Roles (http://dev.perl.org/perl6/doc/design/syn/S12.html#roles)
   will be useful in several ways

 - APIs to the multiple classes within DBI will be defined by Roles.

 - Alternative implementations can be substituted if they 'do' the Role
   (here the Role is acting like a Java Interface).

 - Handles will have references to the objects that provide certain
   services, such as logging, so alternative implementations can be
   substituted on a per-handle basis.

 - As an alternative to manipulating the internals of the handle,
   applications could compose new anonymous classes by mixing multiple
   roles.  Here's an extract from the roles docs url above:

     Run-time mixins are done with does and but. The does binary operator
     is a mutator that derives a new anonymous class (if necessary) and binds
     the object to it:

       $fido does Sentry

     The does operator returns the object so you can nest mixins:

       $fido does Sentry does Tricks does TailChasing does Scratch;

     Unlike the compile-time role composition, each of these layers on a
     new mixin with a new level of inheritance, creating a new anonymous
     class for dear old Fido, so that a .chase method from TailChasing hides
     a .chase method from Sentry.

 - As a result of this ability I'd expect there to be many CPAN modules
   offering roles that can be composed into handles in this way.

 - Choosing between subclassing components of the DBI internals
   or compile-time/run-time subclassing of handles via role mixins
   will depend on the particular functionality required.

At this point I think it's time to start sketching out what the roles
look like and what the guts of a handle looks like. Then we can reduce
the degree of generality and vagueness we're dealing with at the moment.
(But I might distract you with a thread on DSNs first ;-)

To HAVE-A handle or to BE-A handle, that is the question:

So, where does all that leave us with our original question?

Should an applications $dbh be a driver $dbh, blessed into some random
class within the driver, or should it be a wrapper object (provided by
the DBI) with a fixed class (like DBI::db)?

The former is faster, avoiding the need for re-dispatching method calls,
but the latter makes subclassing easier.

I'm thinking along the lines of "make subclassing possible rather than
easy, and then encapsulate it so it's easy again" :)

Basically go with "DBI handle IS-A driver handle" but also supply a
module that provides a transparent 'proxy' object which HAS-A driver
handle.  Then anyone wanting to subclass the DBI would use that as the
base class. (I know, I should say "subclass the DBI" without qualifying
it but I'll duck that for now.)

The win is that the price for re-dispatching the method calls is only
paid by those who want to use it.

Tim.