I have a Factory class that returns a writer strategy based on the extension of a given file:
public static function getWriterForFile($file)
{
// create file info object
$fileInfo = new \SplFileInfo($file);
// check that an extension is present
if ('' === $extension = $fileInfo->getExtension()) {
throw new \RuntimeException(
'No extension found in target file: ' . $file
);
}
// build a class name using the file extension
$className = 'MyNamespace\Writer\Strategy\\'
. ucfirst(strtolower($extension))
. 'Writer';
// attempt to get an instance of the class
if (!in_array($className, get_declared_classes())) {
throw new \RuntimeException(
'No writer could be found for the extension: ' . $extension
);
}
$instance = new $className();
$instance->setTargetFile($file);
return $instance;
}
All of my strategies implement the same interface, for example:
class CsvWriter implements WriterStrategyInterface
{
public function setTargetFile($file)
{
...
}
public function writeLine(array $data)
{
...
}
public function flush()
{
...
}
}
I want to be able to test this method using a dummy extension so that my tests are not dependant on any particular strategy existing. I tried creating a mock for the interface with a set classname, but this does not seem to have declared the mock class name:
public function testExpectedWriterStrategyReturned()
{
$mockWriter = $this->getMock(
'MyNamespace\Writer\Strategy\WriterStrategyInterface',
array(),
array(),
'SssWriter'
);
$file = 'extension.sss';
$writer = MyNamespace\Writer\WriterFactory::getWriterForFile($file);
$this->assertInstanceOf('MyNamespace\Writer\Strategy\WriterStrategyInterface', $writer);;
}
Is there any way for me to stage a mock writer strategy for the factory to load, or should I refactor the factory method to make it more testable?
The main purpose and responsibility for that factory is the creation of objects.
Imho you should test that using
$this->assertInstanceOf('class', $factory->getWriterForFile($file));
Why not abstract further?
You could beimplementation in a way so that the factory dispatches the object creation to another class.
Having a "object creator" that does:
$class = new ReflectionClass($class);
$instance = $class->newInstanceArgs($args);
or something along those lines but what is your gain apart from "well the test looks more like a unit test"? You're not improving really improving your code base and changes just for test-abilities sake always smell a little funny to me.
I'd treat factory tests as integration/wiring tests that make sure all your factory actually work and produce the desired objects.
The only change I'd suggest for your current code sample would be to change two things:
a) make the factory method non static
If you don't have a very good reason you don't gain anything from a static factory except that you can't inject it and making it static makes it accessible from global scope so getting dependencies into the factory will require even more globals and so on. If you do DI with factories usually making them proper objects too helps avoiding issues down the road
b) Don't do diskIo in the factory. Use: getWriterForFile(\SplFileInfo $file)
The factory should not care about the file system. If it needs a existing file it should require one and leave the details of how to handle the error to the consumers.
That gives you the benefit that you can also pass a SplTempFileObject which will make testing easier and allow your factories to be independent of the file system even for production purposes.
Related
I want to design a stateless class, for reusing the same instance in several places of the application without have any side effect. This is necessary because many dependency injection containers always return the same instance of the class.
Let's assume we have the DirectoryUtils class:
<?php
class DirectoryUtils{
private $dir;
public function __constructor($dir){
if($this->checkDirectory($dir)){
$this->dir = $dir;
}else{
throw new Exception("Invalid Directory");
}
}
public function deleteAllFiles(){
// code to delete all files in $this->dir;
}
public function renameDirectory($newName){
// code to rename $this->dir name to $newName
}
private function checkDirectory($dir){
// check if directory exists, is writable...
}
}
A single instance of this class is uncomfortable to reuse. How to make it stateless?
I think you need to widen the scope you are investigating here: what is a meaningful service you can put in the DI container for reuse?
The problem with your class is not that it's stateful, but that its name reflects a misunderstanding of its purpose. This class represents a specific directory so should be named appropriately, e.g.
$my_home_dir = new Directory('/home/imsop');
$your_home_dir = new Directory('/home/abskmj');
$diff_tool->compareDirs($my_home_dir, $your_home_dir);
In your DI container, you would then put several specific instances of this class, for the specific directories you need to access, e.g.
[
'CacheDir' => function($config) {
return new Directory($config['cache_path']);
},
'LogDir' => function($config) {
return new Directory($config['log_path']);
}
]
Another type of service you might create is a factory, which abstracts part of the file system, and gives you different Directory objects, e.g.:
$my_home_dir = $factory->getHomeDir('imsop');
Here, the state constructed in the DI might be a base directory to work within:
[
'DirectoryFactory' => function($config) {
return new DirectoryFactory($config['base_dir_path']);
}
]
Neither of these classes is "stateless", but both are immutable - once constructed, you do not change them to point at a different directory, you use a different instance for each purpose.
The DirectoryFactory class could in fact be stateless by having all the logic hard-coded (e.g. "a home directory is always '/home/' . $user_name"). This could still be useful to put in the DI container, because you could substitute a version with different hard-coded rules, or a test mock. However, as shown, the lack of state is not a necessary pre-condition for it being useful as a "singleton" in this sense.
How to make it stateless
You do not talk about 'stateless' here. See https://en.wikipedia.org/wiki/Stateless
Make your functions static: https://secure.php.net/manual/en/language.oop5.static.php
i.e.
class DirectoryUtils {
...
public static function renameDirectory($newName) {
...
}
}
then you simply call it like this:
DirectoryUtils::renameDirectory($name);
The basic rule for a stateless class is not having any instance variables/properties to store the state. The class methods are similar to utility or helper function working on the arguments only.
Rewriting your class:
<?php
class DirectoryUtils{
public function deleteAllFiles($dir){
// code to delete all files in $dir;
}
public function renameDirectory($dir, $newName){
// code to rename $dir name to $newName
}
}
I am trying to understand the role of a Dependency Injection Container because it strikes me as fundamental in maintainable code.
As I understand it, a DIC is just as the title suggests: a container where all your dependencies are collected together. Instead of seeing new Foo\Bar all over the application, all the new instances are generated inside of the container and then passed through to each other where they are needed (e.g., Model is instantiated with an instance of Database, which is instantiated with an Instance of Config).
I have attempted to make a very simple DIC. This is the result.
In my front controller I am instantiating a new App\Core\Container.
My Container looks like this:
<?php
namespace App\Core;
use App\Config;
class Container
{
public $config;
public $router;
public $database;
public $model;
public $view;
public $controller;
public function __construct()
{
$this->config = new Config;
$this->router = new Router;
$this->database = new Database($this->config);
}
public function add()
{
// add dependencies from the outside?
}
public function getInstance(/* string */)
{
// return an instance for use somewhere?
}
public function newModel($model)
{
$model = $this->getModelNamespace() . $model;
$this->model = new $model($this->database);
return $this->model;
}
private function getModelNamespace()
{
$namespace = 'App\Models\\';
if (array_key_exists('namespace', $this->params = [])) {
$namespace .= $this->params['namespace'] . '\\';
}
return $namespace;
}
public function newView($params)
{
$this->view = new View($this->model, $params);
return $this->view;
}
public function newController($controller)
{
$controller = $this->getControllerNamespace() . $controller;
$this->controller = new $controller;
return $this->controller;
}
private function getControllerNamespace()
{
$namespace = 'App\Controllers\\';
if (array_key_exists('namespace', $this->params = [])) {
$namespace .= $this->params['namespace'] . '\\';
}
return $namespace;
}
}
Questions
Could my implementation above, although very simple, be classed as a basic dependency injector?
Is a Dependency Injection Container generally comprised of one class?
Note: the first three headings answer your questions, while the following ones answer anticipated questions and provide coverage of anything in the first two sections.
Could this be classified as a dependency injection container?
No, this does not look like a dependency injection container. A dependency injection container is meant to reduce the work that instantiation requires by determining, creating, and injecting all dependencies. Rather what you have there appears to be a combination of a factory and a service locator.
Factories abstract the creation of objects. This is essentially what your Container class is doing. By calling designated methods (i.e., newModel), your container takes on the responsibility of locating the exact object to be instantiated and constructing an instance of that object.
The reason I would call this a "poor" factory is that it's beginning to look like it might be used to locate services. Service locators work by hiding an object's dependencies: instead of being dependent on GenericService, an object might depend on a service locator. Given the service locator, it can request an instance of GenericService. I see similar behavior beginning to take hold in your add() and getInstance() methods. Service locators are generally considered anti-patterns because they abstract dependencies therefore making code impossible to test!
Is a dependency injection container comprised of one class?
It depends. You could very easily make a simple dependency injection container with one class. The issue is that the nature of a simple container tends to get more advanced into a not-so-simple container. When you start improving your pattern, you need to consider how the different components play together. Ask yourself: do they follow SOLID principles? If not, refactoring is necessary.
What is a dependency injection container?
I said it above, but again: a dependency injection container is meant to reduce the work that instantiation requires by determining, creating, and injecting all dependencies. A DIC will look at all dependencies of a class, and all dependencies those dependencies may have, and so on... In this sense, the container is responsible for hierarchically instantiating all dependencies.
The Container class you provide relies on very strict definitions of pre-defined classes. For example, classes in your model layer appear to only be dependent on a database connection. (Similar statements can be said about classes in your controller & view layer).
How does a dependency injection container find dependencies?
A dependency injection container will detect dependencies. Typically this happens through 1 of 3 mechanisms: autowiring, annotations, and definitions. PHP-DI docs provide a good idea of what all three of these entail here. In short, though: autowiring detects dependencies by reflecting on a class, annotations are used to write in dependencies using comments above a class, and definitions are used to hard-code dependencies. Personally, I prefer autowiring because it's clean & simple.
Can I create a simple dependency injection container or no?
Yes, you can. Start with the idea that an injector should be able to instantiate any object (service, view, controller, etc...). It needs to look at the relevant object and hierarchically instantiate all dependencies (hint: possibly through some method of recursion).
A quick example of a simple injector using autowiring looks like this:
<?php
class Injector
{
public function make($className)
{
$dependencies = [];
//Create reflection of the class-to-make's constructor to get dependencies
$classReflection = new ReflectionMethod($className, "__construct");
foreach($classReflection->getParameters() as $parameter) {
$dependencyName = $parameter->getClass()->getName();
//Use the injector to make an instance of the dependency
$dependencies[] = $this->make($dependencyName);
}
$class = new ReflectionClass($className);
//Instantiate the class with all dependencies
return $class->newInstanceArgs($dependencies);
}
}
Tested with something like the following, you can see how the injector recursively checks and instantiates all dependencies
class A {
protected $b;
public function __construct(B $b) { $this->b = $b; }
public function output(){ $this->b->foo(); }
}
class B {
protected $c;
public function __construct(C $c) { $this->c = $c; }
public function foo() { $this->c->bar(); }
}
class C {
public function __construct() { }
public function bar() { echo "World!"; }
}
$injector = new Injector;
$a = $injector->make("A");
//No need to manually instantiate A's dependency, B, or B's dependency, C
$a->output();
This basic injector has obvious faults. For example, there is an opportunity to create a recursion disaster if two classes are dependent on each other (there should be a check for that). However, as is, this works as a basic example of what an injector looks like.
Injector vs. Dependency Injection Container
To make this more powerful and fall under the definition of "dependency injection container", you'd want a way to share instantiated instances across multiple make() calls. For example, you may have another method called share(). This method would store the instance passed to it. Whenever a class is built through the make() method and depends on a class previously shared, instead of instantiating a new instance, it would use the already-instantiated one.
For a simple & powerful dependency injection container I suggest Auryn, but by all means, try to understand & create your own before using the ones already available.
I have three classes:
a Logger that logs process information to a file
a Checker that validates input data
an Operations that does things on the input data.
I need Logger in both Checker and Operations to output (log) the process.
I need Checker in Operations, in order to check validity of data.
class Logger {
}
class Checker {
// inherit Logger ?
// dependency-inject Logger ?
// access Logger statically ?
// compose Logger as singleton or create new object ?
}
class Operations {
// inherit Logger ?
// dependency-inject Logger ?
// access Logger statically ?
// compose Logger as singleton or create new object ?
}
The application will create only one instance of Operations and Checker classes. The question is - in situations where no new objects are needed or created, what type of class should Logger be and how should it be implemented in the Operations and Checker classes?
If you are programming to interfaces, then the most flexible option is to use a decorator:
interface ILogger
{
function log($msg);
}
class FileLogger implements ILogger{
function log($msg)
{
file_put_contents('file.dat', $msg . "\n", FILE_APPEND);
}
}
interface IChecker
{
function check($var);
}
class Checker implements IChecker {
function check($var)
{
//do some checking
return true;
}
}
//decorator
class LoggingChecker implements IChecker
{
private $checker;
private $logger;
function __construct(IChecker $checker, ILogger $logger)
{
$this->checker = $checker;
$this->logger = $logger;
}
function check($var)
{
$checkResult = $this->checker->check($var);
$this->logger->log('check result is: ' . ($checkResult)? 'a success' : 'a failure');
return $checkResult;
}
}
interface IOperations
{
function doOperation($var);
}
class Operations implements IOperations{
private $checker;
function __construct(IChecker $checker)
{
$this->checker = $checker;
}
function doOperation($var)
{
if($this->checker->check($var)){
//do some operation
}
}
}
//composotion root
//create concrete logger, in this case a FileLogger instance, though you could latter create a SqlLogger or EmailLogger
//and swap it without any changes to the other classes
$logger = new FileLogger();
//create concreate checker
$checker = new Checker();
//create decorated checker
$loggingChecker = new LoggingChecker($checker, $logger);
//Operations can now be instantiated with either the regular checker, or the decorated logging checker, and it will
//work just the same, with no knowledge of the existense of loging, or indeed any knowledge of how the checker functions, beyond
//the fact it has a method called check that excepts a single parameter
$operation = new Operations($checker); //no logging is done
//OR
$operation = new Operations($loggingChecker); //logging is done
Note that i only created a decorator for IChecker in the above example for berevity.
You could also create a decorator for IOperations eg LoggingOperations that works in the same way - it depends on an instance of ILogger and IOperations.
You would instantiate it with the same concrete ILogger implementation ($logger) and IOperations implementation ($operation).
The class that uses this object would have a single dependancy on IOperations and could be instantiated with either $operation or $logginOperation and behave in the same way.
Hopefully this example gives you an idea of the flexibility of programming to interfaces and how the decorator pattern can simplify dependent classes and help enforce SRP
Answering directly to your question, what kind of class should logger be...
A classic example of a true singleton is a logging service. Suppose we
have an event-based logging service: Client objects request that text
be logged by sending a message to the logging service. Other objects
actually log the text somewhere (console, file, whatever) by listening
to the logging service for these logging requests and handling them.
First, notice that the logging service passes the classic test for
being a singleton:
The requesters need a well-known object to which to send requests to
log. This means a global point of access. Since the logging service is
a single event source to which multiple listeners can register, there
only needs to be one instance.
More info here Why we should consider the «Logger» class as a singleton?
For a nice logger, in case you dont have one at your framework, you should take a look of this one klogger
It depends , is there a possibility to have logger objects with different properties ? (e.g. to write the log into other folders or do something different with the message to be logged based on their properties) If so dependency injection is the way.
Does the logger perform the same way and doesn't even need properties ? (e.g. it just write the msg to a predefined file relative to the source folder). Than you don't even need to use singleton it could be a Utilities class with static methods.
And finally if your logger needs initialization and you initialize it only once then you could use singleton.
Lately I have been trying to create my own PHP framework, just to learn from it (As we may look into some bigger and more robust framework for production). One design concept I currently have, is that most core classes mainly work on static functions within classes.
Now a few days ago, I've seen a few articles about "Static methods are death to testability". This concerned me as.. yeah.. my classes contain mostly static methods.. The main reason I was using static methods is that a lot of classes would never need more than one instance, and static methods are easy to approach in the global scope. Now I'm aware that static methods aren't actually the best way to do things, I'm looking for a better alternative.
Imagine the following code to get a config item:
$testcfg = Config::get("test"); // Gets config from "test"
echo $testcfg->foo; // Would output what "foo" contains ofcourse.
/*
* We cache the newly created instance of the "test" config,
* so if we need to use it again anywhere in the application,
* the Config::get() method simply returns that instance.
*/
This is an example of what I currently have. But according to some articles, this is bad.
Now, I could do this the way how, for example, CodeIgniter does this, using:
$testcfg = $this->config->get("test");
echo $testcfg->foo;
Personally, I find this harder to read. That's why I would prefer another way.
So in short, I guess I need a better approach to my classes. I would not want more than one instance to the config class, maintain readability and have easy access to the class. Any ideas?
Note that I'm looking for some best practice or something including a code sample, not some random ideas. Also, if I'm bound to a $this->class->method style pattern, then would I implement this efficiently?
In response to Sébastien Renauld's comments: here's an article on Dependency Injection (DI) and Inversion of Control (IoC) with some examples, and a few extra words on the Hollywood principle (quite important when working on a framework).
Saying your classes won't ever need more than a single instance doesn't mean that statics are a must. Far from it, actually. If you browse this site, and read through PHP questions that deal with the singleton "pattern", you'll soon find out why singletons are a bit of a no-no.
I won't go into the details, but testing and singletons don't mix. Dependency injection is definitely worth a closer look. I'll leave it at that for now.
To answer your question:
Your exaple (Config::get('test')) implies you have a static property in the Config class somewhere. Now if you've done this, as you say, to facilitate access to given data, imagine what a nightmare it would be to debug your code, if that value were to change somewhere... It's a static, so change it once, and it's changed everywhere. Finding out where it was changed might be harder than you anticipated. Even so, that's nothing compared to the issues someone who uses your code will have in the same situation.
And yet, the real problems will only start when that person using your code wants to test whatever it is he/she made: If you want to have access to an instance in a given object, that has been instantiated in some class, there are plenty of ways to do so (especially in a framework):
class Application
{//base class of your framework
private $defaulDB = null;
public $env = null;
public function __construct($env = 'test')
{
$this->env = $env;
}
private function connectDB(PDO $connection = null)
{
if ($connection === null)
{
$connection = new PDO();//you know the deal...
}
$this->defaultDB = $connection;
}
public function getDB(PDO $conn = null)
{//get connection
if ($this->defaultDB === null)
{
$this->connectDB($conn);
}
return $this->defaultDB;
}
public function registerController(MyConstroller $controller)
{//<== magic!
$controller->registerApplication($this);
return $this;
}
}
As you can see, the Application class has a method that passes the Application instance to your controller, or whatever part of your framework you want to grant access to scope of the Application class.
Note that I've declared the defaultDB property as a private property, so I'm using a getter. I can, if I wanted to, pass a connection to that getter. There's a lot more you can do with that connection, of course, but I can't be bothered writing a full framework to show you everything you can do here :).
Basically, all your controllers will extend the MyController class, which could be an abstract class that looks like this:
abstract class MyController
{
private $app = null;
protected $db = null;
public function __construct(Application $app = null)
{
if ($app !== null)
{
return $this->registerApplication($app);
}
}
public function registerApplication(Application $app)
{
$this->app = $app;
return $this;
}
public function getApplication()
{
return $this->app;
}
}
So in your code, you can easily do something along the lines of:
$controller = new MyController($this);//assuming the instance is created in the Application class
$controller = new MyController();
$controller->registerApplication($appInstance);
In both cases, you can get that single DB instance like so:
$controller->getApplication()->getDB();
You can test your framework with easily by passing a different DB connection to the getDB method, if the defaultDB property hasn't been set in this case. With some extra work you can register multiple DB connections at the same time and access those at will, too:
$controller->getApplication->getDB(new PDO());//pass test connection here...
This is, by no means, the full explanation, but I wanted to get this answer in quite quickly before you end up with a huge static (and thus useless) codebase.
In response to comments from OP:
On how I'd tackle the Config class. Honestly, I'd pretty much do the same thing as I'd do with the defaultDB property as shown above. But I'd probably allow for more targeted control on what class gets access to what part of the config:
class Application
{
private $config = null;
public function __construct($env = 'test', $config = null)
{//get default config path or use path passed as argument
$this->config = new Config(parse_ini_file($config));
}
public function registerController(MyController $controller)
{
$controller->setApplication($this);
}
public function registerDB(MyDB $wrapper, $connect = true)
{//assume MyDB is a wrapper class, that gets the connection data from the config
$wrapper->setConfig(new Config($this->config->getSection('DB')));
$this->defaultDB = $wrapper;
return $this;
}
}
class MyController
{
private $app = null;
public function getApplication()
{
return $this->app;
}
public function setApplication(Application $app)
{
$this->app = $app;
return $this;
}
//Optional:
public function getConfig()
{
return $this->app->getConfig();
}
public function getDB()
{
return $this->app->getDB();
}
}
Those last two methods aren't really required, you could just as well write something like:
$controller->getApplication()->getConfig();
Again, this snippet is all a bit messy and incomplete, but it does go to show you that you can "expose" certain properties of one class, by passing a reference to that class to another. Even if the properties are private, you can use getters to access them all the same. You can also use various register-methods to control what it is the registered object is allowed to see, as I've done with the DB-wrapper in my snippet. A DB class shouldn't deal with viewscripts and namespaces, or autoloaders. That's why I'm only registering the DB section of the config.
Basically, a lot of your main components will end up sharing a number of methods. In other words, they'll end up implementing a given interface. For each main component (assuming the classic MVC pattern), you'll have one abstract base-class, and an inheritance chain of 1 or 2 levels of child classes: Abstract Controller > DefaultController > ProjectSpecificController.
At the same time, all of these classes will probably expect another instance to be passed to them when constructed. Just look at the index.php of any ZendFW project:
$application = new Zend_Application(APPLICATION_ENV);
$application->bootstrap()->run();
That's all you can see, but inside the application, all other classes are being instantiated. That's why you can access neigh on everything from anywhere: all classes have been instantiated inside another class along these lines:
public function initController(Request $request)
{
$this->currentController = $request->getController();
$this->currentController = new $this->currentController($this);
return $this->currentController->init($request)
->{$request->getAction().'Action'}();
}
By passing $this to the constructor of a controller class, that class can use various getters and setters to get to whatever it needs... Look at the examples above, it could use getDB, or getConfig and use that data if that's what it needs.
That's how most frameworks I've tinkered or worked with function: The application is kicks into action and determines what needs to be done. That's the Hollywood-principle, or Inversion of Control: the Application is started, and the application determines what classes it needs when. In the link I provided I believe this is compared to a store creating its own customers: the store is built, and decides what it wants to sell. In order to sell it, it will create the clients it wants, and provide them with the means they need to purchase the goods...
And, before I forget: Yes, all this can be done without a single static variable, let alone function, coming into play. I've built my own framework, and I've never felt there was no other way than to "go static". I did use the Factory pattern at first, but ditched it pretty quickly.
IMHO, a good framework is modular: you should be able to use bits of it (like Symfony's components), without issues. Using the Factory pattern makes you assume too much. You assume class X will be available, which isn't a given.
Registering those classes that are available makes for far more portable components. Consider this:
class AssumeFactory
{
private $db = null;
public function getDB(PDO $db = null)
{
if ($db === null)
{
$config = Factory::getConfig();//assumes Config class
$db = new PDO($config->getDBString());
}
$this->db = $db;
return $this->db;
}
}
As opposed to:
class RegisteredApplication
{//assume this is registered to current Application
public function getDB(PDO $fallback = null, $setToApplication = false)
{
if ($this->getApplication()->getDB() === null)
{//defensive
if ($setToApplication === true && $fallback !== null)
{
$this->getApplication()->setDB($fallback);
return $fallback;//this is current connection
}
if ($fallback === null && $this->getApplication()->getConfig() !== null)
{//if DB is not set #app, check config:
$fallback = $this->getApplication()->getConfig()->getSection('DB');
$fallback = new PDO($fallback->connString, $fallback->user, $fallback->pass);
return $fallback;
}
throw new RuntimeException('No DB connection set #app, no fallback');
}
if ($setToApplication === true && $fallback !== null)
{
$this->getApplication()->setDB($fallback);
}
return $this->getApplication()->getDB();
}
}
Though the latter version is slightly more work to write, it's quite clear which of the two is the better bet. The first version just assumes too much, and doesn't allow for safety-nets. It's also quite dictatorial: suppose I've written a test, and I need the results to go to another DB. I therefore need to change the DB connection, for the entire application (user input, errors, stats... they're all likely to be stored in a DB).
For those two reasons alone, the second snippet is the better candidate: I can pass another DB connection, that overwrites the application default, or, if I don't want to do that, I can either use the default connection, or attempt to create the default connection. Store the connection I just made, or not... the choice is entirely mine. If nothing works, I just get a RuntimeException thrown at me, but that's not the point.
Magic methods would help you: see the examples about __get() and __set()
You should also take a look at namespaces: it may help you to get rid of some classes with static methods only.
I have a DataMapperFactory and I think I am doing it correctly and it makes sense to have one but I have a DomainObjectFactory too but it just seems pointless. This is it:
namespace libs\factories;
use models as Models;
class DomainObjectFactory {
public function build($name) {
$className = 'Models\\' . $name;
return new className();
}
}
The only advantage I can see of this is that I am keeping the new operator from being present all over my code.
There has to be more to a DomainObjectFactory than this right?
Any help would be great thanks.
There are there major reasons to use factories:
1. Abstract the creation of object
This is one of the most useful structures in your architecture when it comes to unit testing. Having a factory be responsible for the creation of instance makes easier to introduce mocks when testing.
Also, as added benefit, your is not anymore tightly coupled to the name of the classes that you utilize.
2. Simplify instantiation
Here you have two aspect that you have to consider. First - the ability to instantiate different objects based on some condition - was already quite well described in helmbert's answer (+1 for him).
The other case is when you are instantiating domain objects, which more complex.
Something like this:
$employees = new EmployeeCollection;
$address = new Location;
$class = $type . `Company`;
$company = new $class( $employee, $address );
There is quite a lot to do before you can create an instance of HoldingCompany. But this whole process can be done withing the factory. Especially if your domain object factory makes a good use of correctly implemented DIC (which is quite rare, btw).
3. Prepare objects before they are released in the application
You should never do any computation in the constructor. It make impossible to test that code. Constructors should only contains simple variable assignments.
But this introduces an issue: sometimes you need to do few logical operations, before you can let other code structures to deal with your instantiated object. As beginners we usually do that in the constructor. But where to put it now?
This is where factories come to the rescue.
public function create( $name )
{
$instance = new $name;
if ( is_callable($instance, false, 'prepare') )
{
$instance->prepare();
}
return $instance;
}
Now, when you use $factory->create('foobar'), your object is fully primed to be used.
In general, you can use the factory to abstract from specific implementations. If you use the new <classname> operator, you instantiate a specific class every time. If you want to interchange this class with another implementation at a later time, you will have to manually change every new statement.
The factory pattern allows you to abstract from specific classes. A valid minimal use case might be something like this:
interface UserInterface {
public function getName();
}
class UserImplementationA implements UserInterface {
private $name;
public function getName() { return $this->name; }
}
class UserImplementationB implements UserInterface {
public function getName() { return "Fritz"; }
}
class UserFactory {
public function createUser() {
if (/* some condition */) return new UserImplementationA();
else return new UserImplementationB();
}
}
$f = new UserFactory();
$u = $f->createUser(); // At this point, you don't really have to care
// whether $u is an UserImplementationA or
// UserImplementationB, you can just treat it as
// an instance of UserInterface.
One use case (of many) when this becomes extremely useful is when working with unit tests. In Test-Driven Development, you often replace dependencies of classes with mock objects (objects that implement a certain interface, but don't really do anything). Using the factory pattern, it is quite easy to transparently substitute specific classes with mock classes.
public function build($name) {
$className = 'Models\\' . $name;
return new $className();
}
That would work for you.
Defining object factories is a good practice, when you would like to set some default properties to objects, and also, you will not have to worry in what namespace or directory some class exists.
Example:
public function createButton($name){
require("home/lib/display/Button.php") ;
$button = new Button($name, "some default param") ;
$button->visible = true ;
return $button ;
}
You just make default objects so quickly via such factories, besides keeping word new away.