Refactoring the Front Controller of the Zend Framework

One of the most fundamental decision in object design is deciding where to put responsibilities. No one, and I mean no one, gets it right the first time. That’s why refactoring is so important. As Kent Beck puts it, refactoring is the process of taking a system and adding to its value, not by changing its behaviour but by giving it more of these qualities that enable us to continue developing at speed.

Extract Class Refactoring

You’ve probably heard that a class should handle a few clear responsibilities. In practice, classes grow. You add some operations here, a bit of data there. You add a responsibility to a class feeling that it’s not worth a separate class, but as that responsibility grows and breeds, the class becomes too complicated. Extract Class is a common technique for moving features between objects.

Extract Class:

You have one class doing work that should be done by two.

Zend Framework

Zend Framework organizes code in a project structure and puts the project files into different directory structures:

  1. MVC directory structure
  2. Modular directory structure

The framework allows users to choose between one or the other. My goal is to move this responsibility away from the Zend_Controller_Front class. To do this I need to use the Extract Class to alter the internal structure of the class without changing its external behaviour. This refactoring will reduce the complexity of the Front Controller and increase its flexibility. Also, it will allow users to define custom directory names and paths.

First, I need to identify the methods I want to extract from the Zend_Controller_Front class:

addControllerDirectory()
setControllerDirectory()
getControllerDirectory()
removeControllerDirectory()
addModuleDirectory()
setModuleControllerDirectoryName()
getModuleControllerDirectoryName()

Then, I need to create a set of classes to express the split-off responsibilities:

Zend_Controller_Directory_Abstract
Zend_Controller_Directory_Exception
Zend_Controller_Directory_Application
Zend_Controller_Directory_Module

And finally, I need to use Move Field and Move Method to move fields and methods over from Zend_Controller_Front to the new classes.

abstract class Zend_Controller_Directory_Abstract
{
    public function setControllerDirectoryName()
    public function getControllerDirectoryName()
    public function setControllerDirectory()
    public function getControllerDirectory()
    public function addControllerDirectory()
    public function removeControllerDirectory()
}

class Zend_Controller_Directory_Application
  extends Zend_Controller_Directory_Abstract
{
    public function addApplicationDirectory()
    public function setApplicationDirectory()
    public function getApplicationDirectory()
}

class Zend_Controller_Directory_Module
  extends Zend_Controller_Directory_Abstract
{
    public function addModuleDirectory()
    public function setModuleDirectory()
    public function getModuleDirectory()
}

All I need to do now is add a setter and getter method to the Zend_Controller_Front class and inject the object. For the sake of this example, I’ll assume that I can add additional methods to the Zend_Controller_Front class.

class Zend_Controller_Front
{
    public function setDirectory(Zend_Controller_Directory_Abstract $directory)
    {
        $dirs = $directory->getControllerDirectory();
        foreach ($dirs as $module => $dir) {
          $this->getDispatcher()->addControllerDirectory($dir, $module);
        }
        $this->_directory = $directory;
    }

    public function getDirectory()
    {
        return $this->_directory;
    }
}

Before:

$frontController = Zend_Controller_Front::getInstance();
$frontController->throwExceptions(true);
$frontController->addControllerDirectory('../application');
$frontController->setModuleControllerDirectoryName('controllers');

After:

$directory = new Zend_Controller_Directory_Application();
$directory->setControllerDirectoryName('controllers');
$directory->addApplicationDirectory('../application');

$frontController = Zend_Controller_Front::getInstance();
$frontController->throwExceptions(true);
$frontController->setDirectory($directory);

That’s it. I’ve demonstrated how to refactor the Front Controller of the Zend Framework using a refactoring known as “Extract Class”. Martin Fowler discusses this technique in “Refactoring: Improving the Design of Existing Code“.

Links

About these ads

8 thoughts on “Refactoring the Front Controller of the Zend Framework

  1. Pingback: DUODRACO

  2. Interesting demonstration, except IMHO the implementation of Zend_Controller_Front::setDirectory(). That method needs to list each variation of Zend_Controller_Directory concrete instance. If someone want to provide his own concrete class, he has to alter the controller’s setDirectory() code. An alternative solution would consist in passing the front controller instance to the Zend_Controller_Directory object. Then that object configures the dispatcher itself. No more hard coded types in the controller’s setDirectory() method.

  3. You are right, the getControllerDirectory() method returns all the paths, so there’s no need to check the instance of the object. I’ve updated the example.

  4. Pingback: Mrasnika’s Lair

  5. Pingback: Zend Framework Controller: 22% Drop in Responsiveness

  6. Pingback: Implementing your own Front Controller in Zend Framework « fede.carg ( blog )

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s