I have a dilemma on class designing.
I'm doing my best to respect SOLID principles but I don't know how to handle dependency injection.
Here is my dilemma:
I read it is a bad practice to instantiate objects inside classes to avoid introducing dependency. So where should our dependencies be created in a full object application? In a special object which is only responsible for dependency instantiations? If yes, what is the name of this object and how to define it? Is it what we call "controller"?
This "controller", what is the right way to unit test it? Should we unit test it?
In a full POO application, how to avoid passing our objects (often the same) between classes? For example, a DB object, Log, ... In this way, we take the risk to have constructors with many parameters, don't we?
In order to illustrate my dilemma, I tried to create a use case.
I want to create a script (that I partially implemented below) that generates a file and print another one:
<?php
/**
* Generate a file, add it to the queue and print the next one
*/
class Script
public function run() {
#Generate file
$fileComputor = new FileComputer(...);
$file = $fileComputor->compute();
#Instantiate dependencies for printing
$db = new Db(new PdoAdapter());
$printerDriver = new Driver(new HttpRequest(new CurlAdapter()));
$log = new Log($db);
$queue = new Queue($db);
$statsUpdater = new StatsUpdater($db);
$monitor = new Monitor(new StatsdDriver(new SocketAdapter()));
#Add generated file to the queue
$queueModel->push($file);
#Print the next file on queue if existing
$printer = new Printer($printerDriver, $log, $queue, $monitor, $statsUpdater);
$printer->print();
}
}
class Printer {
protected $_driver;
protected $_log;
protected $_queue;
protected $_monitor;
protected $_statsUpdater;
/**
* $driver : Driver used to send documents to the printer
* $log : Log actions in database
* $queue : Handle the print queue
* $monitor : Send metrics to Statsd (to feed the graphit GUI)
* $statsdUpdater : Consolidate the statistics database
*/
public function __construct($driver, $log, $queue, $monitor, $statsUpdater) {
$this->_driver = $driver;
$this->_log = $log;
$this->_queue = $queue;
$this->_monitor = $monitor
$this->_statsUpdater = $statsUpdater;
}
public function print() {
if ($this->_queue->hasNext()) {
$file = $this->_queue->getNext();
$this->_driver->print($file);
$this->_log->log('File has been printed');
$this->_monitor->sendCount(1);
$this->_statsUpdater->increment();
}
}
}
?>
What do you think about this implementation?
Every feature we will want to plug into our Printer class will result into a new dependency to pass to the constructor (if for example we want to also generate a syslog, to measure time that takes the printer to process, etc).
In a close future, we will have between 10 and 15 parameters into the constructor call.
So where should our dependencies be created in a full object application? In a special object which is only responsible for dependency instantiations?
You have 2 options:
you create all the objects yourself, at the root of your application, i.e. in your front controller (index.php) for example. If you application is a bit big, that becomes quickly a hell.
you use a Dependency Injection Container. That object will be responsible of creating objects (and injecting them their dependencies in the constructor). Same here: you have to use/call the container only at the root of your application, i.e. in the front controller (index.php) for example.
If yes, what is the name of this object and how to define it? Is it what we call "controller"?
That's the Container. To give you an example, here is PHP-DI - Understanding DI.
You can use dependency injection on the controller (and I would recommend to do it): you can get dependencies in the controller's constructor (just like in any service). Some frameworks makes that difficult though (Symfony for example).
This "controller", what is the right way to unit test it? Should we unit test it?
No really. Some containers allow you to configure "Factories" to generate some objects.
For example, if creating the DBConnection object is complex, you could write a factory class, that has a method that creates the DBConnection object. So you could test the factory class. But I wouldn't say that's necessary.
In a full POO application, how to avoid passing our objects (often the same) between classes?
You should never pass instances around, because you should never call a constructor: all objects are constructed by the container.
So it becomes really simple: you write each class by taking dependencies in the constructor, and that's it. You don't care about dependencies and what those dependencies need.
For example, a DB object, Log, ... In this way, we take the risk to have constructors with many parameters, don't we?
Yes. You said you expect to have like 15-20 parameters in the constructor: that's not good at all.
You should generally try to have 2-3 parameters maximum. Having to many means that your class has too much responsibilities, it does to many things.
You can try splitting up the code of your class into several smaller/more targeted classes, or use events for example.
If we take your example, your printer could rather be like:
public function print($file) {
$this->driver->print($file);
$this->log->log('File has been printed');
$this->monitor->sendCount(1);
$this->statsUpdater->increment();
}
It makes more sense: a printer prints a file.
It's one dependency less (the queue). And then you can have a PrintQueueProcessor that watches the queues, takes the next file and calls the printer to print it.
The printer does one job (print a file), the queue processor does one job (unqueue files to print them).
Related
I'm not new to PHP or programming at all. But recently I was thinking about website programming in PHP and how easier it was before the OOP. Anyway, I prefer OOP than the old procedural style.
I want to implement a website but it seems I always have to use a global or a static variables. And I'm starting to wonder, how can I do it without those?
Anyway, what I'm talking about is having a class for each "component" of the website.
For example if it was an url shortener website it would be: links, members, database.
What I'm talking about is way more complicated, at least 8 classes.
Anyway, my current approach is the following:
$database = new Database(...);
$links = new Links($db);
$users = new Users($db);
Anyway, for example I want to get all the links a user posted by its ID, I need to use both links and both users components.
Is there any other way I could do this? Any other approach? except passing them as constructor parameters.
You should have the following components:
Business objects, which model and express one particular "thing" in your app:
class Link { ... }
class User { ... }
These don't "do" anything, they're just there to formalise your data structures. These objects have getter and setter methods to get and set individual attributes, which are also validated there:
public function setUrl($url) {
if (!/* validate the URL here*/) {
throw new InvalidArgumentException("$url is not a valid URL");
}
$this->url = $url;
}
Minimum required data is part of the constructor. This ensures your data integrity application-wide. It allows you to assert that when you have an instance of Link, the data expressed by it is minimum valid data for a link.
A database link. Only the bare necessary thing to connect to a database, nothing more, nothing less. A raw PDO or mysqli object will do just fine.
A data-object mapper, which takes a database link and knows how to store business objects in the database and how to retrieve them:
class LinkStorage {
protected $db;
public function __construct(PDO $db) {
$this->db = $db;
}
}
This class has all the various methods of how to retrieve things from your database:
public function getById($id) {
$stmt = $this->db->prepare('SELECT ... FROM ... WHERE id = :id');
$stmt->execute(compact('id'));
if (!$data = $stmt->fetch()) {
throw new RuntimeException("Record with id $id does not exist");
}
return new Link($data['url']);
}
You can have all sorts of different queries encapsulated this way, e.g.:
/**
* Returns all links by a particular user.
* #param User $user
* #return Link[]
*/
public function getAllFromUser(User $user) {
...
}
The usage is then simple:
$db = new PDO(...);
$linkStorage = new LinkStorage($db);
$userStorage = new UserStorage($db);
$user = $userStorage->getById($id);
$links = $linkStorage->getAllFromUser($user);
This kind of code would then be encapsulated in a service class, which holds all the possible "actions" you can do in your app. registerUser(array $data), getLinksOfUser($id), newLinkFromPostData(array $data) etc.
What I've just described is basically the model portion of an MVC-style application. The other two parts would be controllers which call the service methods, and views which output data retrieved from service methods. This approach keeps responsibilities separate and isolated and allows you to put higher-level logic and functionality together like building blocks. Business objects are the lowest building block, their structure needs to be solid and well defined for the rest to work. Data-object mappers just concern themselves with putting those objects into the database and getting them back out again. Services then put all this together in various complex ways and make things happen.
You shouldn't have any cyclic dependencies with this, as responsibilities are well separated. Your individual dependencies may still be somewhat complex. If it becomes too cumbersome to instantiate classes, you'll want to look into Factories:
$factory = new Factory;
$userStorage = $factory->newUserStorage();
All the complexity of instantiation is encapsulated in this factory. One step further are dependency injection containers, who you can configure in, for example, an XML file to specify which class depends on what, and then the DI container will take care of it for you.
I was thinking about website programming in PHP and how easier it was
before the OOP
Well, stick to procedural then. If it is easier to write a well written website in a procedural or functional way then opposed to the ojbect-oriented way. Stick ti what you are used to. OO isn't better then functional. It's just a different approach.
the public void main() in php
In the lanuage Java every piece of software we write has a single entry point. The public void main() method. This method fires up the entire application and passes in the arguments provided on startup. It is also the only exit point in the application. the application ends in this method (unless it crashes).
In php, there is no single entry point. We have a bunch of files that run some scripts that do some more stuff and then somewhere along the line another script decides to return stuff and die();
Dependency injection and how IoC libraries can help
When using dependency injection, it becomes a real pain in the a$$ when creating objects and passing arround the correct instance of a class. We start solving this problem with ugly solutions: Singleton, globals, statics, ... Making our software more and more tightly coupled and harder to maintain.
Inversion of Control can help here. there are some really greate articles on the webz.
You can use autoloading in PHP for a better solution:
http://php.net/manual/en/language.oop5.autoload.php
I'm not new to PHP or programming at all. But recently I was thinking about website programming in PHP and how easier it was before the OOP. Anyway, I prefer OOP than the old procedural style.
I want to implement a website but it seems I always have to use a global or a static variables. And I'm starting to wonder, how can I do it without those?
Anyway, what I'm talking about is having a class for each "component" of the website.
For example if it was an url shortener website it would be: links, members, database.
What I'm talking about is way more complicated, at least 8 classes.
Anyway, my current approach is the following:
$database = new Database(...);
$links = new Links($db);
$users = new Users($db);
Anyway, for example I want to get all the links a user posted by its ID, I need to use both links and both users components.
Is there any other way I could do this? Any other approach? except passing them as constructor parameters.
You should have the following components:
Business objects, which model and express one particular "thing" in your app:
class Link { ... }
class User { ... }
These don't "do" anything, they're just there to formalise your data structures. These objects have getter and setter methods to get and set individual attributes, which are also validated there:
public function setUrl($url) {
if (!/* validate the URL here*/) {
throw new InvalidArgumentException("$url is not a valid URL");
}
$this->url = $url;
}
Minimum required data is part of the constructor. This ensures your data integrity application-wide. It allows you to assert that when you have an instance of Link, the data expressed by it is minimum valid data for a link.
A database link. Only the bare necessary thing to connect to a database, nothing more, nothing less. A raw PDO or mysqli object will do just fine.
A data-object mapper, which takes a database link and knows how to store business objects in the database and how to retrieve them:
class LinkStorage {
protected $db;
public function __construct(PDO $db) {
$this->db = $db;
}
}
This class has all the various methods of how to retrieve things from your database:
public function getById($id) {
$stmt = $this->db->prepare('SELECT ... FROM ... WHERE id = :id');
$stmt->execute(compact('id'));
if (!$data = $stmt->fetch()) {
throw new RuntimeException("Record with id $id does not exist");
}
return new Link($data['url']);
}
You can have all sorts of different queries encapsulated this way, e.g.:
/**
* Returns all links by a particular user.
* #param User $user
* #return Link[]
*/
public function getAllFromUser(User $user) {
...
}
The usage is then simple:
$db = new PDO(...);
$linkStorage = new LinkStorage($db);
$userStorage = new UserStorage($db);
$user = $userStorage->getById($id);
$links = $linkStorage->getAllFromUser($user);
This kind of code would then be encapsulated in a service class, which holds all the possible "actions" you can do in your app. registerUser(array $data), getLinksOfUser($id), newLinkFromPostData(array $data) etc.
What I've just described is basically the model portion of an MVC-style application. The other two parts would be controllers which call the service methods, and views which output data retrieved from service methods. This approach keeps responsibilities separate and isolated and allows you to put higher-level logic and functionality together like building blocks. Business objects are the lowest building block, their structure needs to be solid and well defined for the rest to work. Data-object mappers just concern themselves with putting those objects into the database and getting them back out again. Services then put all this together in various complex ways and make things happen.
You shouldn't have any cyclic dependencies with this, as responsibilities are well separated. Your individual dependencies may still be somewhat complex. If it becomes too cumbersome to instantiate classes, you'll want to look into Factories:
$factory = new Factory;
$userStorage = $factory->newUserStorage();
All the complexity of instantiation is encapsulated in this factory. One step further are dependency injection containers, who you can configure in, for example, an XML file to specify which class depends on what, and then the DI container will take care of it for you.
I was thinking about website programming in PHP and how easier it was
before the OOP
Well, stick to procedural then. If it is easier to write a well written website in a procedural or functional way then opposed to the ojbect-oriented way. Stick ti what you are used to. OO isn't better then functional. It's just a different approach.
the public void main() in php
In the lanuage Java every piece of software we write has a single entry point. The public void main() method. This method fires up the entire application and passes in the arguments provided on startup. It is also the only exit point in the application. the application ends in this method (unless it crashes).
In php, there is no single entry point. We have a bunch of files that run some scripts that do some more stuff and then somewhere along the line another script decides to return stuff and die();
Dependency injection and how IoC libraries can help
When using dependency injection, it becomes a real pain in the a$$ when creating objects and passing arround the correct instance of a class. We start solving this problem with ugly solutions: Singleton, globals, statics, ... Making our software more and more tightly coupled and harder to maintain.
Inversion of Control can help here. there are some really greate articles on the webz.
You can use autoloading in PHP for a better solution:
http://php.net/manual/en/language.oop5.autoload.php
First of all, sorry for my bad English, I hope you understand what I'm saying.
Here is my problem:
Lets assume i have an MVC application including standard router, controller, model(service) layer and some kind of db connector.
Model layer depends on a db connector, controllers depends on models/services and the top-level "application" class depends on routers and controllers.
My object hierarchy looks like this:
App -> ControllerFactory -> ServiceFactory -> DAO -> DbConnection
Perhaps, written above doesn't look like best application architecture ever, but i want to focus on the other thing:
When i'm trying to instantiate an App class i should pass all dependencies to the class instantiated; class dependencies, in turn, has their own dependencies and so on.
As a result I get all hierarchy stack instantiated at once. But what if i dont need to access the database in some cases; what if some controllers are used for rendering static templates without model interaction?
I mean, what if there are some special cases when class does not require its own dependencies(and in some cases it does)? Should i inject dependencies conditionaly or something?
I'm really stuck at this point and i don't know what to do.
Update: after re-reading carefully your question, here is another advice: yes, every class has different dependencies.
Don't inject every object into every other object. For example, some services might need DAOs, so inject them. But if a service doesn't need a DAO, don't inject any DAO.
The rest of my answer is valid if you have (for example) a service that needs a DAO (and thus a DB connection) not for every method.
What you may be looking for is lazy injection.
It is the act of injecting a dependency not loaded, so that the object is loaded only if/when used.
In conrete terms, that means injecting a proxy object, that would look like and behave exactly like the original object (for example, the db connection).
Several DI container (frameworks) support this so you don't have to create proxies yourself. I'll take as an example PHP-DI (I work on that project FYI).
Here is an example using annotations:
use DI\Annotation\Inject;
class Example {
/**
* #Inject(lazy=true)
* #var My\Class
*/
protected $property;
/**
* #Inject({ "param1" = {"lazy"=true} })
*/
public function method(My\Class $param1) {
}
}
Of course if you don't want to use annotations you can use any other configuration you want (PHP, YAML, …). Here is the same example by configuring the container in pure PHP:
$container->set('Example')
->withProperty('property', 'My\Class', true)
->withMethod('method', array('param1' => array(
'name' => 'My\Class',
'lazy' => true,
)));
See more in the documentation about Lazy Injection.
Note: you may not be using a Container for now (and that's not a problem), but for tackling lazy injection this is a fair amount of work and you might need to start considering using one.
If your dependency construction is complex, simply add a new factory class that should contain all the logic to create a correct object for you.
class AppFactory(){
__construct(all params){
}
build(useDB=true){
// logic to build
if(useDB){
App = new App(new ControllerFactory(new ServiceFactory(new DAO(new DbConnection(params)))))
} else {
App = new App(new ControllerFactory(new ServiceFactory(null))))
}
return App;
}
}
I have a question concerning dependency injection. I have been keeping it simple so far, my methodology is basically to factor out object creation within objects and passing it instead in the constructer. I have come to a point where I am attacking larger classes that require multiple oblects. Some even have objects that contain other objects, with merry little singletons here and there. It gets ugly fast when testing these classes, as they are far from 'isolated' they are still hard-coded to their dependencies.
So. Injecting an object or 2 for a trivial class is straightforward,
I have looked into dependency containers, saw many implementations and am now wondering what is the advantage of using container vs. a registry for example. Couldn't one just as easily use a registry to hold anonymous functions that create the needed dependencies when called upon?
The 2 containers I peeked into, Php Dependency and Pimple differ greatly in the implementation.
I am wondering on the advantages of user a container vs. passing straight objects. I fail to understand how php-dependency's implementation would be tested, ie how would one implement the mock database object in phpunit without the actual class being injected when tested? Is there advantage to having dependency mapped out and used in doctags like this?
Class Book {
private $_database;
/**
* #PdInject database
*/
public function setDatabase($database) {
$this->_database = $database;
}
}
Pimple, on the other hand takes a totally different approach. No docblock tags, no mapping in seperate file, it seems like some kind of souped up registry ....
Objects are defined by anonymous functions that return an instance of the object:
// define some parameters
$container['cookie_name'] = 'SESSION_ID';
$container['session_storage_class'] = 'SessionStorage';
... that can behave as a factory at same time:
$container['session'] = function ($c) {
return new Session($c['session_storage']);
};
Declaring shared ressources always serves the same instance (singleton!?):
$c['session'] = $c->share(function ($c) {
return new Session($c['session_storage']);
});
This is were I got the idea of using a simple registry that holds either objects or anonymous functions. BUt am I missing something in this approach? Pimple, I can see to how to test, but Php-Dependency is unclear to me from a testing point of view.
Normally in our apps, we do constructor injection and define an interface for all components in our system:
class Book
{
/**
* #var Db_AdapterInterface
*/
private $_database;
public function __construct(Db_AdapterInterface $database)
{
$this->_database = $database;
}
}
We have then of course a standard Db_Adapter and then another Db_TestAdapter. In Db_TestAdapter we can define results of SQL queries in our tests.
For our normal app, we have something like this for our container:
$container->add('Db_AdapterInterface', new Db_Adapter());
And then in our tests, we have this line instead:
$container->add('Db_AdapterInterface', new Db_TestAdapter());
To get an instance of a Book, we simply ask the container for it:
$book = $container->construct('Book');
And the container injects all the needed dependencies into the object.
If you keep all your objects loosely coupled, ie object A only needs an interface B then you can always provide object A with a test implementation. At that point what container you use doesn't matter.
We have a very simple IoC container which can do basic constructor injection. Our tests inherit from a base class which fills the container with standard test objects. That way we don't have a lot of code just to construct an object we want to test.
Update:
I added an example of wiring things up in the container.
I hear people talking about dependency injection and the benefit of it all the time, but I don't really understand it.
I'm wondering if it's a solution to the "I pass database connections as arguments all the time" problem.
I tried reading wikipedia's entry on it, but the example is written in Java so I don't solidly understand the difference it is trying to make clear. ( http://en.wikipedia.org/wiki/Dependency_injection ).
I read this dependency-injection-in-php article ( http://www.potstuck.com/2009/01/08/php-dependency-injection/ ), and it seems like the objective is to not pass dependencies to an object directly, but to cordon off the creation of an object along with the creation of it's dependencies. I'm not sure how to apply that in a using php functions context, though.
Additionally, is the following Dependency Injection, and should I bother trying to do dependency injection in a functional context?
Version 1: (the kind of code that I create, but don't like, every day)
function get_data_from_database($database_connection){
$data = $database_connection->query('blah');
return $data;
}
Version 2: (don't have to pass a database connection, but perhaps not dependency injection?)
function get_database_connection(){
static $db_connection;
if($db_connection){
return $db_connection;
} else {
// create db_connection
...
}
}
function get_data_from_database(){
$conn = get_database_connection();
$data = $conn->query('blah');
return $data;
}
$data = get_data_from_database();
Version 3: (the creation of the "object"/data is separate, and the database code is still, so perhaps this would count as dependency injection?)
function factory_of_data_set(){
static $db_connection;
$data_set = null;
$db_connection = get_database_connection();
$data_set = $db_connection->query('blah');
return $data_set;
}
$data = factory_of_data_set();
Anyone have a good resource or just insight that makes the method and benefit -crystal- clear?
Dependency injection is a big word for "I have some more parameters in my constructor".
It's what you did before the awfull Singleton wave when you did not like globals :
<?php
class User {
private $_db;
function __construct($db) {
$this->_db = $db;
}
}
$db = new Db();
$user = new User($db);
Now, the trick is to use a single class to manage your dependencies, something like that :
class DependencyContainer
{
private _instances = array();
private _params = array();
public function __construct($params)
{
$this->_params = $params;
}
public function getDb()
{
if (empty($this->_instances['db'])
|| !is_a($this->_instances['db'], 'PDO')
) {
$this->_instances['db'] = new PDO(
$this->_params['dsn'],
$this->_params['dbUser'],
$this->_params['dbPwd']
);
}
return $this->_instances['db'];
}
}
class User
{
private $_db;
public function __construct(DependencyContainer $di)
{
$this->_db = $di->getDb();
}
}
$dependencies = new DependencyContainer($someParams);
$user = new User($dependencies);
You must think you just another class and more complexity. But, your user class may need something to log messages like lot of other classes. Just add a getMessageHandler function to your dependency container, and some $this->_messages = $di->getMessageHandler() to your user class. Nothing to change in the rest of your code.
You'll get lot of infos on symfony's doc
Your first example IS dependancy injection, you are injecting the dependency on the database object into the function.
Sarah has said this isn't, but imo it is, I believe she is thinking of dependency injection containers which are the next level up:
http://components.symfony-project.org/dependency-injection/trunk/book/02-Dependency-Injection-Containers
None of your examples look like dependency injection, version one is the closest though. Dependency injection is a technique used in object oriented programming, where the constructor of an object has arguments for the service objects it needs, and those service objects are passed in by the creator of the instance (which could be a factory, a test, or a dependency injection framework).
To get around your 'always passing the connection object' problem you may want to consider the template pattern. The template pattern is basically an abstract base class with the common part of a repeated code block, and abstract methods to allow for the variation between the instances of those repeated code blocks. Basically the base is a template of a block of code, and the abstract methods are the blanks to be filled in. I personally use the template method pattern to do my database resource control in Java.
I have done much searching on this topic myself (PHP Dependency Injection) and haven't found much to my liking. A lot has been written on the subject for other languages (Google Guice - http://code.google.com/p/google-guice/ ; Java Spring), but I couldn't find much available for PHP. Regardless of the language, however, the challenges are similar.
The three versions you list in your question are the typical approach. Version 3 is the closest to the direction in which I have seen the industry going. By shifting the responsibility of creating your dependent objects outside of your class, you are free to manipulate them as you please in your test code. However, the problem that I encountered with that approach is that you end up with long chains of dependent objects in your constructor that can potentially not even be used by the receiving object, but get passed through to an secondary dependent object. It gets messy and you lose knowledge of what is coming from where.
The Dependency Container example by #Arkh and #mmmshuddup is a great start, but I nonetheless found limitations with that approach as well. The final solution upon which I arrived was a custom built solution modeled somewhat after the Cake Pattern popular in Scala. It allows you to pass a single dependency into each of your constructors AND it lets you define the default construction of the dependent objects per class. This frees you from long dependency chains as well as losing control of the default implementations of your dependencies.
I called the system Diesel and I've been really happy with it. I published the code on github for anyone interested. You can get to it from the blog I wrote on the subject, which describes the basic usage as well as goes into more detail on your question. http://developers.blog.box.com/2012/02/15/introducting-diesel-php-dependency-injection/
Dependency Injection is the idea of removing the dependency between 2 components in order to focus on why they are dependent.
Imagine you have a component A that needs to use the services of another component B.
If you hardcode the existence of B inside A, then you will be stuck when you will want A to use the sames services, but implemented by another component.
So usually, you define a service interface that B and C will implement, and you make sure that when you use A, you feed it with objects compatible with the needed interface.
In your case, you might consider that your interface is a service on which you can make a query.
Your first case is the one that is the closer to the idea of Dependency Injection.