Testable Factories
So I wrote a post about testable classes in PHP, and before I even hit "Publish" I read something on Stack Overflow that challenged some of my opinions. I wrote that I didn't need testable factories, but what if I did?
For me, the main appeal of a factory is one-line instantiation of classes. This allows for clean, clear dependency injection in object instantiation, but quick access to an object without a lot of duplicated code, and also has the potential to reduce overhead when creating an interface to a data store. (In my previous example, the factory method cached a reference to the database object using a static.)
But what if the factory itself were its own class?
class UserFactory {
public static function userstore( $new_store = null ) {
static $userstore;
if( $new_store !== null ) {
$userstore = $new_store;
}
// default userstore if one wasn't provided
if( $userstore === null ) {
$userstore = new UserStore_Database( DB_USER, DB_PASS );
}
return $userstore;
}
public static function load_by_id( $id ) {
$user = new User( self::userstore() );
$user->load( $id );
return $user;
}
}
$dbstore = new UserStore_Database( DB_USER, DB_PASS );
UserFactory::userstore( $dbstore );
$user = UserFactory::load_by_id( 12 );
Or maybe it's better to have the factory as an object rather than a collection of static methods:
class UserFactory {
public $userstore;
public function __construct( $userstore ) {
$this->userstore = $userstore;
}
public function load_by_id( $id ) {
$user = new User( $this->userstore );
$user->load( $id );
return $user;
}
}
$dbstore = new UserStore_Database( DB_USER, DB_PASS );
$uf = new UserFactory( $dbstore );
$user = $uf->load_by_id( 12 );
I'm not sure if one implementation is better than the other. The former seems testable, and it can be used in any scope without instantiation or prior setup, allowing for one-liners.