in reply to DESTROY for tied classes

I am sorry, but I still don't see what you are winning with the tie.

I see what you are losing - you have significantly complicated your life so you can slow down every access by an order of magnitude. But OO is not good just because it is OO. There is nothing magical about the method-call syntax that makes it better. It is just a different way of saying the same thing with a little polymorphic magic.

Now there are many things that you could do which would make the tie make sense. For instance often you want to have a different implementation look like a tie. An example would be to have an object with a set of keys that it would use (so that typos of a key would trigger a warning). Another would be a hash that was stored persistently on disk. Yet another would be an interface into a C structure. In each of these cases the tie is winning you something specific - something that in all likelyhood has little directly to to with the capabilities you want to expose.

In that case it makes no sense to intertwine the package that you tie the hash into with the package that has methods you are exporting. Indeed you drop this incestuous relationship as chromatic suggested and your problem just goes away.

My suggestion therefore is to simply drop the tie. If at a later point you find a need for it, you can easily add it. Probably it will just be a matter of building your tie implementation and modifying the constructor.

Remember that the point of modularity, interface hiding, and all that isn't that your first implementation will be gold-plated. Rather it is that you can get a working system and then be able to modify it in directions that experience shows are important...

Replies are listed 'Best First'.
Re: Re (tilly) 1: DESTROY for tied classes
by MeowChow (Vicar) on Dec 05, 2000 at 06:49 UTC
    I don't yet know what I'm winning with the tie either, because it's use is as yet unforseen -- it's actually part of a sort of "class-generator" module for Perl, and the use for this feature will be up to those who use the module. I decided to throw this feature into the class generator because the class generator will also form the basis of a DBI persistence layer I'm working on, hence one of your suggested tie usages.

    But yes, with chromatic's suggestion, I can keep the tie and lose the "incestuous relationship", as you've humorously phrased it, so it's all good :)

      I would suggest still losing it. If you later decide you want the tie in certain submodules, consider the following trick:
      package A; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $obj; %$obj = @_; return bless ($obj, $class); } sub TrialMethod { print "The method was called\n"; } package A::SubClass; @ISA = A; sub new { my $proto = shift; my $obj = $proto->SUPER::new(@_); tie (%$obj, 'Some::Tie::Class', $obj); return $obj; } package Some::Tie::Class; sub FETCH { print "A fetch happened\n"; } sub TIEHASH { my $class = shift; my %hash = %{ shift() }; return bless \%hash, $class; } package main; my $thing = new A::SubClass(qw(hello world)); $thing->TrialMethod(); $thing->{foo};
      See? The example is useless, but it shows that without taking the hit of assuming a tie implementation in your base class you have in no way affected your ability to create subclasses that can take advantage of a tie. You are already this polymorphic. Why force the speed hit?

      In fact the generic approach is more polymorphic than the tie implementation you are doing. Why? Because you moved key initializations into TIEHASH, so anyone who wants to override your tie with an interesting implementation needs to couple their TIEHASH more tightly with yours than they should need to.

      In fact this is a basic principle of OO design which is good to know. The point of OO is to provide encapsulated behaviour, aspects of which are easy to override. Therefore in your design do as little as you need to with as clean an interface as you can come up with, and plan on using the ease of overriding to later add on any features that could come in handy. Then anyone who doesn't use the flexibility, doesn't pay. But the potential is still intact.

        I guess I didn't make myself very clear in my last response -- when I say I'm writing a class generator, I mean that I'm designing a module with functionality similar to Class::MethodMaker. It is not a base class that I'm writing, but a module that generates class methods from "boilerplate" at run-time, thereby simplifying recurring issues that come up when writing OO Perl, like class-level and base-class-level data, attribute defaults, attribute accessors/mutators, etc. In practice, there will be no speed hit if the option to tie the class is not used, since no "tieing code" will be generated. I do want to leave the programmer the option to create such code; however, so I can simplify the process of writing such code as well.

        Although you've now got me questioning whether there is any point in writing code to generate from "boilerplate" TIEHASH/FETCH/STORE routines when they will in probably just get overridden anyway. I definitely have to think in greater depth about what sort of generated code could even be useful in regards to the tie feature. Thanks for the insight.