Hello,

In order to test my perl scripts, I want to override global variables (defined with the our keyword in a separated module).

Basically I have a working solution, but I don't really know if there's a better way to do that. And I need some clarifications.

To explain my issue, I reduced the code to 3 files :

- consts.pm which declare globals variables and set their content.

- logging.pm which will use consts.pm and use the global vars

- run-unit-tests.pl which overrides the content of these variables

My current solution is like this :

consts.pm
use Exporter; our @ISA = 'Exporter'; our @EXPORT = qw($VAR1 $VAR2); our $VAR1="var1"; our $VAR2="var2"; 1;
logging.pm
use consts; our ($VAR1, $VAR2); print "Import...\n"; print "VAR1 : [$VAR1]\n"; print "VAR2 : [$VAR2]\n"; sub logging_func() { print "Running function...\n"; print "VAR1 : [$VAR1]\n"; print "VAR2 : [$VAR2]\n"; } 1;
run-unit-tests.pl
use consts; our ($VAR1, $VAR2); local $VAR1 = "override1"; local $VAR2 = "override2"; use logging; logging_func();

The produced output is like this :

Import... VAR1 : [var1] VAR2 : [var2] Running function... VAR1 : [override1] VAR2 : [override2]

Note that I use "local" because seems like this is the good option to override global vars (I'm reading the camel book). Seems like the override only works when I call the function. That's weird because I modified the value before including the logging module.

Other topic, could you please tell me when and why I should use (or not use) the Exporter core module. Because removing it seems to have no impact at all...

Next 3 code snippets produce the same output without teh use of Exporter code module.

consts.pm
our $VAR1="var1"; our $VAR2="var2"; 1;
logging.pm
use consts; our ($VAR1, $VAR2); print "Import...\n"; print "VAR1 : [$VAR1]\n"; print "VAR2 : [$VAR2]\n"; sub logging_func() { print "Running function...\n"; print "VAR1 : [$VAR1]\n"; print "VAR2 : [$VAR2]\n"; } 1;
use consts; our ($VAR1, $VAR2); #print "VAR1 : [$VAR1]\n"; #print "VAR2 : [$VAR2]\n"; local $VAR1 = "override1"; local $VAR2 = "override2"; use logging; logging_func();

When I run perl run-unit-tests.pl I get this output:

Import... VAR1 : [var1] VAR2 : [var2] Running function... VAR1 : [override1] VAR2 : [override2]

I thought that using a package name was a possible solution but it isn't... As you can see on the next code snippets :

consts.pm
use Exporter; package consts; our $VAR1="var1"; our $VAR2="var2"; 1;
logging.pm
use consts; print "Import...\n"; print "VAR1 : [$consts::VAR1]\n"; print "VAR2 : [$consts::VAR2]\n"; sub logging_func() { print "Running function...\n"; print "VAR1 : [$consts::VAR1]\n"; print "VAR2 : [$consts::VAR2]\n"; } 1;
run-unit-tests.pl
use consts; $consts::VAR1 = "override1"; $consts::VAR2 = "override2"; # OR #local $consts::VAR1 = "override1"; #local $consts::VAR2 = "override2"; use logging; logging_func();

This produce the same output :

Import... VAR1 : [var1] VAR2 : [var2] Running function... VAR1 : [override1] VAR2 : [override2]

Note that using "local" keyword during overriding step does not change anything.

If I use $main without specifying the package name, I have the exact same behavior (not a surprise of course).

So to summarize :

- Is it a better solution than mines ?

- Could you please explain this behavior ?

- Should I see any difference if I use require instead of use?

- Why do I have no impact when I stop using Exporter module ? I can't remember why I needed Exporter (maybe because I have "use strict" and "use warnings" in the original scripts...)

I don't really want to use non core modules (I read about PadWalker somewhere). At the moment, I don't really want to use packages if possible (nothing against it, but if there's a solution with packages, there's probably another one without packages).

Thank you a lot by advance.

And... I'm pretty new to perl, and I would say... perl rocks!

Regards.

Thibault


In reply to Seeking the right way to override global variables by contra-sh

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.