- Instantiate Applicaton Object Refactoring
This is a refactoring. It is informed by some experience, but is by no means complete.
++ Intent
Remove coupling with global state to make application reusable in different contexts.
++ Motivation
-
Allows for subclassing applications, which benefits testing
-
Provides for multiple, differently-configured applications, desirable for virtual hosting environments
-
Aesthetics, ease of understanding
++ Mechanics
Presuming you are working on an app named "flarg":
If there is a global {{$flarg}} variable which is an instance of some kind of driver, rename it to {{$flarg_driver}}
In {{lib/base.php}}, create a global {{$flarg}} which is an instance of {{Flarg::}}
For each static method in {{Flarg::}}
Find all calls of the method and replace {{Flarg::method()}} with {{$flarg->method()}}. (Possible exception: if the method is truly static, meaning it will always produce the same output given the same parameters, you might want to keep it static.)
Remove {{@static}} in phpdoc comment
For each global variable ({{$flarg_driver}} is used as an example):
Add a {{getDriver()}} method to {{Flarg::}}
Make {{getDriver()}} return the global variable's value
FInd references to the global variable, and replace each with a call to {{$flarg->getDriver()}} (Note: With PHP4, you may need a temporary variable, since {{$flarg->getDriver()->foo()}} does not parse.)
When all references are replaced, do one of the following:
Move initialization code for the value into the method
Introduce a field, move initialization code into constructor
Introduce a field which defaults to {{null}}, move initialization code into getter, but only execute when the field is {{null}} (Note, beware of introducing cycles.)
When application class gets too heavy to work with, you can use ExtractClass and/or MoveMethod to split up responsibilities.
Ideally, we will eventually end up with an application object which takes all configuration as constructor parameters, does all of the application's work (probably most via delegation - FacadePattern), but does not contain any UI code. Ideal for use from command-line scripts and unit tests.
++ TODO
Open discussion from Horde developers
Check for core developer support for this pattern.
When/how to write tests and run tests for this refactoring?
"Motivation" section needs some work.
...