1

I am working on the largest individual project I have ever worked on - one reason was to learn how the application evolved from a small non-object-oriented project to a massive one that is object-oriented by necessity, and get a more thorough understanding of why different applications necessitate certain architectures.

I originally thought the best way to handle global-scope variables would be to maintain one monolithic class instantiating all of these vars.

class publicValues {

    public static $globalBoolean = false;
    .
    .
    public static $globalCounter = 0; // roughly 600 variables total at this point

}

The idea was to keep all global-scope variables "atomic", but I have run into uncertainty with non-static arrays. (will demonstrate with a dummy example below)

public static $allAmericanStates = array('Alaska', .....); // atomic array including all states in the U.S.

public static $allCanadianProvinces = array('Alberta',.....); // atomic array including all provinces in Canada

//here's the problem
public static $allAmericanStates_UNION_allCanadianProvinces = array_merge($allCanadianProvinces, $allAmericanStates); // CAN'T DO THIS

So my solution was to initialize the unions (array_merge), intersections (array_intersection), subtractions (array_diff), implosions, etc. as public static vars (in the class publicValues, see first code block above):

public static $allAmericanStates_UNION_allCanadianProvinces = '';

and subsequently call a function to perform the relevant operations on the atomic arrays (overwriting the empty string value they were initialized as):

function synthesize_remaining_static_vars() {

    publicValues::$allAmericanStates_UNION_allCanadianProvinces = array_merge($allCanadianProvinces, $allAmericanStates); // so if California secedes I only need to remove CA from publicValues::$allAmericanStates

    publicValues::$implodedAllAmericanStates = implode("|", publicValues::$allAmericanStates); // e.g., for use in preg_match()

    //etc.

}

So this way all the global-scope vars can be initiated in one location, and whenever necessary, they can be accessed using 1 class (e.g., publicValues, instead of multiple classes where non-static vars are referenced using a different class). Furthermore, unions, intersections, etc., need not be maintained because they are just the resultant of operations on the atomic arrays.

This may be an opinion question so I apologize if so. Does anyone see any serious issues with the approach of using one publicly accessible class to hold all global-scope variables? (wrt Code Maintainability, "future-proofing", etc.)

  • Basicly good oop needs no global-scope variables! All is within classes. What you may can use is something like a register class. But dont create global-vars at the first place :) Look here: http://stackoverflow.com/questions/1151341/registry-design-pattern-good-or-bad – JustOnUnderMillions Dec 14 '16 at 17:00
  • Different variables need to be accessed by multiple classes - so you would just set the vars in the __construct() function? -----> e.g., $this->allAmericanStates = publicValues::$allAmericanStates – The One and Only ChemistryBlob Dec 14 '16 at 17:03
  • What you mean is `dependeny injection` and so yes , that is the best way to do it. Set it via `__construct` or `getter/setter` or use one (global/static/injected)`RegistryClass` that holds all the variables for your app. Have a look here: http://pimple.sensiolabs.org/ – JustOnUnderMillions Dec 14 '16 at 17:05
  • can you expand on `600 variables total at this point` ... what are all these static variables? That's a lot of static information and I'm trying to wrap my head around what it could possibly be. – cmorrissey Dec 14 '16 at 17:07
  • @cmorrisey it's a VERY wide scope project - but it's a mix of arrays, Booleans that are specific to different situations, counters, imploded arrays, etc. – The One and Only ChemistryBlob Dec 14 '16 at 17:12

2 Answers2

2

My recommendation would be to use a database for this (e.g. SQLite) as this is essentially what you're trying to emulate.

While I have had a few projects which contained monolithic static registries like this, maintenance eventually becomes unrealistic - especially with ~600 variables.

A proper database setup will also cache intermediate results - like what you're trying to do with $allAmericanStates_UNION_allCanadianProvinces. For this, you should read up on stored procedures. This way, you can delegate all of the optimisation to the database provider and retrieve the data with a standard command as and when you need it.

I often have a singleton helper class to abstract the database commands away from the code for simple retrievals.

Chris Watts
  • 6,197
  • 7
  • 49
  • 98
1

What you're describing is a singleton: https://en.wikipedia.org/wiki/Singleton_pattern

I recommend reading up on design patterns to see the pros and cons of the singleton pattern. Having global variables spread out across many classes doesn't mitigate the cons of having global variables, so in this case, if you must have global variables, a singleton to handle them may be a good idea. As for your merge and intersection variables, those could either be initialized in the singleton's __construct and accessed through getters, or through a static function that returns the result of the merge.

Zackary Murphy
  • 421
  • 5
  • 10