PHP Objects, Patterns and Practice (3rd edition)

(Barry) #1

CHAPTER 18 ■ TESTING WITH PHPUNIT


\woo\domain\ObjectWatcher::instance()->performOperations();
$this->invokeView( $app_c->getView( $request ) );
}


This method is designed to be invoked by the static run() method. The first thing I notice is a very
definite code smell. The Request object is directly instantiated here. That means I can’t swap in a stub
should I want to. Time to pull on the thread. What’s going on in Request? This is the constructor:


// \woo\controller\Request
function __construct() {
$this->init();
\woo\base\RequestRegistry::setRequest($this );
}


That smell’s getting worse. The Request class refers itself to the RequestRegistry so that other
components can get it. There are two things I don’t like about this on reflection. First, the code implies a
direct invocation must take place before the Registry is used to access the Request object. And second,
there’s a bit of unnecessary coupling going on. The Request class doesn’t really need to know about the
RequestRegistry.
So how can I improve my design and make the system more amenable to testing at the same time? I
prefer to push instantiations back to the RequestRegistry where possible. That way later I can extend the
implementation of RequestRegistry::instance() to return a MockRequestRegistry populated with fake
components if I want to. I love to fool my systems. So first off I remove that setRequest() line from the
Request object. Now I push my Request instantiation back to the RequestRegistry object:


namespace woo/controller;


//...


class RequestRegistry extends Registry {
private $request;


// ...


static function getRequest() {
$that = self::instance();
if (! isset( $that->request ) ) {
$that->request = new \woo\controller\Request();
}
return $that->request;
}
}


Finally, I must replace that direct instantiation in the Controller:

// \woo\controller\Controller
function handleRequest() {


$request = \woo\base\RequestRegistry::getRequest();
$app_c = \woo\base\ApplicationRegistry::appController();
while( $cmd = $app_c->getCommand( $request ) ) {
$cmd->execute( $request );
}
\woo\domain\ObjectWatcher::instance()->performOperations();
$this->invokeView( $app_c->getView( $request ) );
}

Free download pdf