in reply to dynamiclly assigning values to global variables in modules

I strongly agree with tobyink here.   The design-issue here is not so much “that global value,” nor how or when it is represented or set, but rather, what and where you do something with it.   Every “what” that you do with it, should be in exactly one “where.”   And that should be ... a set of subroutines, located in just one place, which accept parameters, validate those parameters, and then return a finished work-product (which by-the-by uses this globally-assigned value).

It is also good to “future-proof” your design, writing apparently-redundant subroutines that presently return the same value, but which are named and called based on the meaning of whatever it is that they do.   Two different meanings – use cases – might return identical values today, but they might not do so tomorrow.   Anticipate this early.

The real problem with “global values” is that the logic which actually does something with those values is now scattered to the four winds.   You wouldn’t believe how hard it can be just to move an ill-designed application to a new location having a slightly different subdirectory structure ... because, since the logic to do it is everywhere, therefore dependencies are also everywhere.

In your app, what exactly is $ver_dir for?   I presume that the application will use this to obtain the name of some files, given the file name.   Therefore, write a single routine that does that ... and that checks the name for accuracy, and maybe that checks that the file exists, and so on.   Whatever it is that you do with $ver_dir, do it right here in one module and do it suspiciously:   let it be what will detect that bug.   Write a separate routine for each significant use-case even if each does the same thing.   I can confidently cut many thousands of dollars from the analysis-phase of a legacy project that we’re inheriting, when I see coding-practices like that (instead of what I usually see).