[cvs] [Wiki] created: InstantiateApplicationObjectRefactoring

Jason Felice jfelice at cronosys.com
Tue Aug 15 11:18:44 PDT 2006


eraserhd  Tue, 15 Aug 2006 11:18:44 -0700

Created page: http://wiki.horde.org/InstantiateApplicationObjectRefactoring

+ 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.



More information about the cvs mailing list