[cvs] [Wiki] changed: RemoveGlobals

Jason Felice jfelice at cronosys.com
Wed Aug 16 07:53:37 PDT 2006


eraserhd  Wed, 16 Aug 2006 07:53:36 -0700

Modified page: http://wiki.horde.org/RemoveGlobals
New Revision:  1.3
Change log:  add my rationale, responses to Jan

@@ -1,9 +1,64 @@
-This should be a general landing page for thoughts on and debate about removing globals.
+++ Questions
  
-Should we refactor to remove all global variables and other couplings with global state ($_SESSION, $_REQUEST, singleton pattern, etc)?  We can do this by:
+* Is it desirable to remove all "normal" global variables?
+* How should we consider autoglobals ({{$_SESSION}}, {{$_REQUEST}}, etc.) in relation to "normal" globals?
+* How should we consider static variables within methods in relation to "normal" globals?  (This has implications for the Singleton pattern.)
  
-* Encapsulting request in a request object
+++ Note
+
+I'm not advocating for a whole bunch of developers to attack the code and remove all globals (unless, of course, they feel like it).  I'm advocating for adopting some small practices and habits which will have the eventual effect of removing all globals--or at least enough so that some day we get pissed off enough to finish the job in an evening.  I liken this to Chuck's emphasis on the small practices of factory and singleton patterns, which produced a highly flexible framework uniformly supporting lots of network protocols and database backends as the emergent design. --Jason
+
+++ Jason's Rationale
+
+When I've contributed to projects with fewer global variables, I've noticed that the //flexibility// and //maintainability// of the code has been significantly greater, and therefore it is more enjoyable to work with the code.  My theory: if there are no globals, we can predict that an object doesn't play with any toys that we haven't given it.  This has a number of effects:
+
+With globals, the protocol for usage of an object could be complicated and implicit.  Given the following class:
+
+<code>class Foo {
+    function Foo($number) { ... }
+    function doBar($number) { ... }
+}
+</code>
+
+We might reasonably expect the protocol for using this object to be:
+
+<code>$foo = new Foo(12);
+echo $foo->doBar(47);
+</code>
+
+when in fact, the protocol could be:
+
+<code>$GLOBALS['calculator_helper'] = new CalculatorHelper("pgsql://localhost/db_cache");
+$_SESSION['state'] = 'initializing';
+$foo = new Foo(12);
+$_SESSION['state'] = 'calculating';
+echo $foo->doBar(47);
+</code>
+
+If we were to remove globals, we would have to rewrite the interface for Foo:
+
+<code>class Foo {
+    /**
+     * @param CalculatorHelper:: $helper
+     */
+    function Foo(&$helper, $number) { ... }
+    function setState($name) { ... }
+    function bar($number) { ... }
+}
+</code>
+
+While not perfect, I'm comfortable that this better communicates the object's protocol.
+
+So, a no-globals rule means to me:
+
+# I can reuse objects more confidently in different contexts, since I can trust that it needs only what it explicitly asks for by way of constructor and method call signatures.
+# I can very easily find out what the object depends on by looking at its usage.
+# I can more easily find method calls and constructions of a class, for adding parameters and refactoring and such.
+
+++ How To
+
+* Encapsulate request in an object
  * //Instantiate// master Horde object (e.g. {{$horde = new Horde($config);}})
  * InstantiateApplicationObjectRefactoring
  * Page handling become method object (e.g. {{$page = new Turba_BrowsePage($app, $request); $page->execute();}})
  
@@ -14,4 +69,16 @@
  * Instantiation of the Horde object doesn't make sense to me because it introduces another global object. And why is using a static Horde class bad?
  * Usage of $_SESSION makes a lot of sense to me, because it is very clear that we are dealing with session state. Encapsulating this in a class or object obfuscates the code.
  
  --Jan
+
+----
+
+Given my rationale,
+
+* Like the ApplicationObject, I would want to fold globals into the global {{$horde}} by adding methods like {{getPrefs()}} and {{getBrowser()}}.  Ideally (which is ideally enough that we may never actually get there) we would make eventually make the {{$horde}} unglobal, and construct a Horde object at the top of every page pointing to the config directory.  We would easily end up killing more globals than the one we introduce.
+* A static Horde class isn't "bad" per se (that's relative), but see above--I think we have something to gain.  I think global variables like to hide in them //because// they are static and have no instance data, and so //calls to methods on static classes become implicit dependencies//.
+* The $_SESSION issue (and I'll admit that $_SESSION is the autoglobal I'm the least concerned about) is about making protocol explicit--it's also the easiest to solve.  In my Ingo test I just used {{$ingo = &new Ingo($_SESSION);}} (passed by reference).
+
+I normally try not to spam people with a lot of words, but have failed miserably this time ;-)  Let me know what you think (or anyone else, for that matter).
+
+--Jason


More information about the cvs mailing list