http://qs1969.pair.com?node_id=478896

The module I referenced in my earlier RFC has been released to CPAN as Object::LocalVars (with thanks to simonm for the name suggestion). I'm describing the technique I'm using as "outside-in" objects -- a word play on "inside-out" objects, as there are strong similarities (and one huge difference). It provides a very streamlined approach to coding objects in perl. An excerpt from the POD follows to describe this technique, including a list of features and drawbacks:

NAME

Object::LocalVars - Outside-in objects with local aliasing of $self and object variables

SYNOPSIS

  package My::Object;
  use strict;
  use Object::LocalVars;

  give_methods our $self;  # this exact line is required

  our $field1 : Prop;
  our $field2 : Prop;

  sub as_string : Method { 
    return "$self has properties '$field1' and '$field2'";
  }

DESCRIPTION

This is an early development release. Documentation is incomplete and the API may change. Do not use for production purposes. Comments appreciated.

This module helps developers create "outside-in" objects. Properties (and $self) are declared as package globals. Method calls are wrapped such that these globals take on a local value that is correct for the specific calling object and the duration of the method call. I.e. $self is locally aliased to the calling object and properties are locally aliased to the values of the properties for that object. The package globals themselves are empty and data are stored in a separate namespace for each package, keyed off the reference addresses of the objects.

"Outside-in" objects are similar to "inside-out" objects, which store data in a single lexical hash closure for each property that is keyed off the reference addresses of the objects. Both differ from "traditional" Perl objects, which store data for the object directly within a blessed reference to a data structure. For both "outside-in" and "inside-out" objects, data is stored centrally and the blessed reference is simply a key to look up the right data in the central data store.

Unlike with "inside-out" objects, the use of package variables for "outside-in" objects allows for the use of local symbol table manipulation. This allows Object::LocalVars to deliver a variety of features -- though with some drawbacks.

Features

  • Provides $self automatically to methods without my $self = shift and the like
  • Provides dynamic aliasing of properties within methods -- methods can access properties directly as variables without the overhead of calls to accessors or mutators, eliminating the overhead of these calls in methods
  • Array and hash properties may be accessed via direct dereference of a simple variable, allowing developers to push, pop, splice, etc. without the usual tortured syntax to dereference an accessor call
  • Properties no longer require accessors to have compile time syntax checking under use strict
  • Uses attributes to mark properties and methods, but only in the BEGIN phase so should be mod_perl friendly (though I haven't tested this yet)
  • Provides attributes for public, protected and private properties, class properties and methods
  • Does not use source filtering
  • Orthogonality -- can subclass just about any other class, regardless of implementation. (Also a nice feature of some "inside-out" implementations)

Drawbacks

  • Method efficiency -- wrappers around methods create extra overhead on method calls
  • Minimal encapsulation -- data is hidden but still publically accessible, unlike approaches that use lexical closures to create strong encapsulation
  • Designed for single inheritance only. Multiple inheritance may or may not work depending on the exact circumstances

At this point, it is fully functional, though not yet optimized. Early benchmarking indicates that it can be much faster than other object-oriented techniques in Perl if the number of property accesses within methods is high relative to the number of method calls or it can be slower if the ratio is the other way around. However, the real intention was to streamline development time, with less redundant (and error-prone) typing, so benchmarks are intended to suggest that not too much is lost (and some may even be gained) for the syntactic convenience that Object::LocalVars offers

I encourage any curious monks to experiment with it and post or send feedback, either on the technique itself, the API, benchmarks, etc. to help me plan future refinements.

Thanks,

-xdg

Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.