Better Inside-Out Objects

Ovid on 2006-10-06T16:54:34

Wouldn't it be nice if inside-out objects worked like this?

use base 'Encapsulation';

sub new {
  bless {}, shift;
}

sub foo {
  my $self = shift;
  return $self->{foo} unless @_;
  $self->{foo} = shift;
}

1;

If that was the interface but subclasses and other code couldn't reach inside, wouldn't more people use 'em? I believe most programmers violate encapsulation because they're lazy, not because they've gone rogue or something. Here's how to make that work.


Dev vs. live

ChrisDolan on 2006-10-06T18:30:32

How about setting this at the top:
BEGIN {
   if ($running_on_dev_server) {
      require base;
      base->import('Encapsulation');
   }
}
That gives you protection during testing/development and speed in production (at the risk of REALLY painful bugs if there are flaws in the emulation of Encapsulation.pm).

Alternatively, change the "if" to
  if ($ENV{AUTHOR_TESTING}) {

Re:Dev vs. live

Aristotle on 2006-10-06T20:09:13

No.

Ovid is throwing away half the point of inside-out objects already: compile-time checking of field names. The other half is being agnostic about the implementation of any superclasses; and your suggestion would mean that one could no longer rely on that, either.

You may as well not use inside-out objects at all. (I am reminded of chromatic’s chocolate cake recipe analogy…)

Re:Dev vs. live

ChrisDolan on 2006-10-06T20:15:21

I was simply suggesting that this hack could be used at development time to catch places where external code illegitimately accessed variables via hash values instead of accessor functions.

That is, the encapsulation hack could be put to an alternate use. Especially if the overload function dies if the caller package isn't isa('Encapsulation').

I agree that the "inside-outness" is not significant in this case.

That's not what I call 'inside-out' objects.

Abigail on 2006-10-07T09:21:21

People seem to think that Inside-Out Objects are about not letting other people touch your internals.

They aren't.

Inside-Out Objects solve two out of three problems* I have with traditional Perl OO:

  • It's not benefitting from enabling 'strict' (that is, no compile time checking of attribute names). Now you may say "I don't care about that, I have tests", but that just means you find both 'use strict' and 'use warning' fluff - after all, you have your tests.
  • In an inheritance tree, your implemenation is restricted by the implementation of the classes you inherite, and your implementation restricts the implementation of the classes that inherit from you.

The first point means that OO programming isn't much better than programming in perl4 (not only don't you have the benefits of compile time errors, you don't have name spaces either).

The second point means that Perl is making easy things hard: code reuse is much harder that it should be.

The point of IOO isn't so much that it prevents other classes from accessing the internals (if you want to, changing a few 'my's to 'our's gives access, without giving up any of the other benefits of IOO), it's about giving classes the freedom to do whatever they want, without accidently touching someone elses internals.

The implementation you suggest doesn't solve any of the problems IOO solves. You don't get compile time errors on mistyping attribute names, and you will put a dependency in the inheritance tree.

Now, I won't judge your implementation as good or bad - if it works for you then it should be good enough, if it works for others so much the better. Just don't call it a different way of doing Inside-Out Objects. They aren't.

*: The third point being: too much typing to get to an attribute.

Re:That's not what I call 'inside-out' objects.

Ovid on 2006-10-07T16:32:14

I've evidently been wrong about IOO. Since the major problem I've faced has traditionally been encapsulation, that was the bit I've focused on. I will have to concede all your points. I just find that virtually every IOO implementation I've seen out there has been painful to work with, so I gave up and hope that solving the major problem I have might be good enough.

Re:That's not what I call 'inside-out' objects.

Aristotle on 2006-10-07T18:35:28

Hmm. For me, the visible difference between hash-based and inside-out objects is turning the following:

my $self = shift;
$self->{ bar };

into this:

my $self = refaddr shift;
$bar{ $self };

That seems hardly painful… but then, as MJD says, people are weird about syntax.