jk2addict has asked for the wisdom of the Perl Monks concerning the following question:

I'm not sure thie is really an abstraction issue, but here goes.

While working on a new project, I've noticed myself using the same hash key's over and over in a set of modules, and one thing is starting to bug me: what if I need to change those keys later, either due to programming flaws or just namespace preferences?

So, I was thinking of globalizing these key names, either lexically in each module, or globally in a Constants module. Is this just overkill for the most part, ala Going To Far? Are there any drawbacks to doing this? I don't tend to see a lot of this in current modules, so is there something I don't know?

In web design, I tend to make all my key names of name/value pairs constants for querystrings and form elements for the same reason. If I need to change the name of one later, it's in one place, so I guess this is behaviour is wanting to rub off into my Perl life.

Replies are listed 'Best First'.
(jeffa) Re: Abstraction: Has far is to far?
by jeffa (Bishop) on Aug 26, 2002 at 14:36 UTC
    If you don't mind the performance hit, try to access your hash keys through methods only. That way, if you change the the name of the key, you should only need to change it two or three times - once in the constructor, and once for get/set methods:
    package Foo; sub new { my $class = shift; my $self = { foo => 'bar', baz => 'qux', }; return bless $self, $class; } # 'private' method sub _get_foo { my $self = shift; return $self->{foo}; } # 'public' method sub get_foo { my $self = shift; return $self->_get_foo(); }
    The 'private' accessor has to know the name of the hash key, but the 'public' accessor doesn't. So, if you change foo to bar:
    # 'private' has to change sub _get_foo { my $self = shift; return $self->{bar}; } # but 'public' doesn't sub get_foo { my $self = shift; return $self->_get_foo(); }
    You don't have to track down as many places to change. There are still issues however, such as whether or not calling get_foo() to 'get bar' is acceptable. This is why proper feedback and designing is vital for large projects. However, as Murphy says, "Variables aren't. Constants don't". Also, i find it better to deprecate methods instead of outright removing/renaming them if you do have to change your interface accessor names:
    sub get_foo { my $self = shift; carp "get_foo() is deprecated, use get_bar()"; return _get_bar(); } sub get_bar { my $self = shift; return $self->_get_bar(); }
    Just some food for thought ...

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    

      Thanks for the tap of the ClueStick. If I want to access a modules internal hash data $self->{'data'}, I should really be using a accessor methods; public, private or otherwise. That in itself seems like overkill when I can just use the hash, but it's definately how I should be doing it.

      P.S. OT. Nice Kit.
      I prefer the 5-paradiddle in 4 over 6 myself..

      | R-RR-  R-RR-  R-RR-  R-RR-  |
      | -L--L  -L--L  -L--L  -L--L  |
      |
      | R    R    R    R    R    R  | 
      

Re: Abstraction: Has far is to far?
by perrin (Chancellor) on Aug 26, 2002 at 14:34 UTC
    I have seen people use lexicals for hash keys, but this was more to catch typos:
    use strict; my $bar = 'bar'; $foo{$bar} = 1; $foo{$bor} = 1; # typo, won't compile
    It sounds like you are more interested in abstracting things so that you can change them later, in which case I would ask why you are passing around hashes at all. If these were objects instead, your abstraction would be there, in the class definition, and you could change the hash keys later without editing the other modules that use your class.