I want to emphasize that global *settings* are not really bad (things acting like environment), but global *variables* (meaning that they change to hold different data as the program runs) usually are.
I will further qualify that in Perl specifically, you have the 'local' keyword which can change a global variable to affect only things within that scope, and then it goes back to its original setting at the end of that block. This pattern makes global variables much less messy than in any other language, and I use this pattern in a variety of sticky situations where normal function parameters would be awkward or inefficient.
But, the point still remains that code like this is abjectly terrible:
# This initializes $main::foo
function_one();
# This uses the value of $main::foo and updates it
function_two();
# This relies on the modified value from function_two
function_three();
Why is it so terrible? Because when the maintenance programmer comes along and tries to implement some new feature or fix some bug, they might cause function_two to not get run, and now function_three is broken. The comments I added above are typically not present, and they waste tens of hours hunting high and low through all the code to find out why it broke, and what part of their change caused it.
Compare with:
my $value= function_one();
function_two(\$value);
function_three($value);
Without even having any comments, you can see that $value comes from function_one, that function_two reads and maybe writes it, and that it is used by function_three. These clues dramatically speed up development and debugging. As another benefit, you can refactor this into an object where the _one, _two, _three workflow occurs during method calls. If $value is global, you can't refactor this easily, or even realize that it will be hard to refactor. |