in reply to Avoiding Globals with OO Perl

There is nothing wrong per se with using global variables. It is just the way you use them that counts. If they are used to perform some spooky "action at a distance", then there is something wrong. But global variables used to set some parameters affecting the global working of your program is OK.

I tend to store these global parameters in a hash I call %config and many times I load it from an external config file.

Actually what you are doing is more or less the same, only you have gone one step further and use an object. So you just made it a bit more complex with no benefits to compensate for this complexity. Your way to get data in or out of your object is more difficult than using a hash. It does not protect you from any typos, since you do not even check in your getter method if that slot in your object ever existed beforehand and it is now being created silently (and perhaps wrongly).

I guess your idea is to use this global object to move data in and out of your subroutines without having to use any variable as parameters. I can tell you that is the wrong approach. Subroutines should have a well-defined input and output interface, which should be obvious to any programmer, i.e. the first line of your sub should grab the data in the @_ variable and store it in lexical variables (with meaningful names) and all data returned by the sub should pass through a return statement. A sub should not "leach" or "leak" information in any other way.

CountZero

A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

</div

Replies are listed 'Best First'.
Re^2: Avoiding Globals with OO Perl
by Anonymous Monk on Oct 20, 2011 at 20:02 UTC

    I am learning alot thank you all.

    Want I want to avoid is this. Passing variables to subroutines that don't use them because subs inside need them

    #pass in vars some of which won't be used till deep #nested sub work($a,$b,$c,$d,$e,$f); sub work{ my ($a,$b,$c,$d,$e,$f) = @_; more_work($b,$c); print "$a\n"; } more_work{ my ($b,$c) = @_; even_more_work($c); print "$b\n"; } even_more_work{ $c = shift; print "$c\n"; }
      work($a,$b,$c,$d,$e,$f); sub work{ my ($a,$b,$c,$d,$e,$f) = @_; more_work($b,$c); print "$a\n"; } more_work{ my ($b,$c) = @_; even_more_work($c); print "$b\n"; }

      $d, $e, $f are never used, and $b & $c are only used by more_work().

      Then perhaps what you should be doing is:

      more_work( $b, $c ); work( $a )

      Or if work() requires the results of more_work(), then maybe:

      work( $a, more_work( $b, $c ) );

      I realise that your example was just that, but it demonstrates the problem with using made-up examples rather than real ones. It becomes all too easy to exaggerate the effect of the perceived problem -- that of passing lots of data around -- whilst obscuring what is often the real problem -- poorly structured code.


      With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

      That looks like a candidate for some light weight OO and named parameters. Consider:

      use strict; use warnings; my $obj = bless {flibble => 1, floop => 2, flop => 3}; $obj->work(nuts => 7, bolts => 5); sub work{ my ($self, %params) = @_; $self->more_work(%params); print "$params{nuts}\n" if $self->{flibble}; } sub more_work{ my ($self, %params) = @_; $self->even_more_work(%params); print "$params{bolts}\n" if $self->{floop} > 1; } sub even_more_work{ my ($self, %params) = @_; my $sum = $params{nuts} + $params{bolts}; print "$sum\n" if $self->{flop} == 3; }

      Although in real code a constructor would check important parameters and subs would check that any required named parameters are as expected.

      True laziness is hard work
      You know, you've faced the problem of my everyday erlang reality. There is no such thing as a global variables, but (sic!) there is a process-dictionary, the State and things alike. So, anyway, you need to have some dynamically modifiable in runtime params which you will need only on N-th in depth sub. Just create a hash-like structure and give a link to it in a bunch of your nested subs =)