in reply to Best practices with globals and subroutine arguments

In general, the need for such is usually either a) an indication of too general a data structure; too much in one pot; or b) poorly factored code; doing too many only vaguely related things in each subroutine.

There are occasions--for example; configuration parameters--where it makes some sense to put lots of little things into one encompassing structure. And purely on the basis of your description, this might be one of them. But if all 6 subroutines need access to all 10 variables or structures, why not just wrap them into one encompassing (lexical) structure and pass a reference to that? I won't claim a "best practice" title for this, but it would be easier and probably safer.

Another possibility for avoiding the globals is to make them methods of an "object". You don't even have to go the full OO hog. You can achieve most of the same benefits by using a closures:

{ my( $var1, %var2, @var3, $var4 ... ); sub initVars{ $var1 = ...; %var2 = ...; } sub depSub1 { while( my $k, $v = each %var2 ) { } } sub depSub2 { for my $elem ( @var3 ) { } } }

The above is simple to write and requires virtually no changes to the calling code, but achieves most of what an explicit OO module would achieve. Plus, calling globals "closures" seems to take the sting out of most arguments against them :)

Of course, sticking the keyword package inside the outer set of curlies and having init() return a blessed reference isn't much harder either. But it does require more changes in the calling code.


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.
RIP an inspiration; A true Folk's Guy