i have been trying to get my head round factory patterns and dependency injection and i understand the concepts and basics behind both patterns and that there can be a slight cross over. But before i start coding it up, i just want to check my flow method would be correct.
My intended flow would be...
create a config file with all the properties needed for my 'core classes' in the format
$config['core.classname']['property_name']=$value;
create a factory class that will create an instance of all my core classes and run through the config file injecting the properties in to each class
when my app needs an instance of a class, it uses the factory class to clone the required class which has had its dependencies injected.
As i understand it this would decouple my core classes, allowing for them to be swapped in and out of my code easier.
What you are calling a 'factory' is really more of a dependency injection container. A factory traditionally only creates one type of object.
In general you should avoid creating any core instances until your app actually needs one. You may have 100 core classes defined of which any given app request might only need a couple.
In many cases your app will want to share the same instance or a core class so automatic cloning is probably not quite what you want.
Consider reading through the Service (what you call core) chapter in the Symfony2 framework package for ideas:
http://symfony.com/doc/current/book/service_container.html
Related
I'm writing a little application from scratch, and I wanted to use some packages from packagist. For DI I choosed Auryn.
Now, one of the first thing that I learnt about Auryn is that it tries to avoid to be a Dependency Container and it is explicitily wrote in the docs that you should not use the instance of Auryn as a container, passing it through the various classes of your app.
I'm fine with that, but, because I have a "main" class as a wrapper for all of the backbone of the app, I think that I should have in the constructor of this main class only the dependency of an Injector object (That's the main Auryin object), then in the constructor of the class I should wire everything to be ready for DI and reflection.
The other way around is to not use a main class, and just use clean procedural code in my index file, wiring all togheter at the same way with Auryn.
What do you advice is the best way to proceed?
The idea behind dependency injection is to gather all the information how your various classes are "wired up" in one place (your DI container class / DI config file), instead of spreading and duplicating it all over your code. I presume your "Main"-class is only instanciated once in your Index.php, so it makes no noticeable difference whether you pass the Auryn instance to Main's constructor or use Auryn to get an instance of Main.
Background
I am trying to design a reasonably useful MVC framework from scratch primarilty for my own education before jumping into Laravel/Symfony.
I am trying to implement dependency injection because plan on expanding this framework in the future and I want to keep things modular and maintainable.
Here is the MVC repository: https://github.com/JethroHazelhurst/psr-4-mvc
(Note: the controller/routing system is hard coded for simplicity!)
Here is my flowchart showing how the MVC framework is structured without dependency injection.
As I understand it, the main dependencies are...
Core\Router depends on Foo\Controller
FooController depends on Core\Controller (via the parent::__construct method)
Core\Controller depends on Core\View
Foo_Model depends on Core\model which depends on Core\Database
Questions
So I am a bit confused as to how I should use dependency injection here... for example: How do I implement dependency injection with parent::__constructors (if at all)?
Also, is depending on parent::__construct like this making the framework too tightly coupled?
Many thanks in advance for your considered reply.
You will actually need to implement dependency injection then. Presently there is none; no object are being passed their dependencies. In your constructors, you should be receiving the objects needed for correct execution. It's the basis of dependency injection.
Dependency injection would happen at the bootstrap phase of an application. I think of bootstrap as the action of preparing the environment to actually handle whatever it is called to do, in our case handling a http request.
Generally an index.php only calls a bootstrap.php file. That bootstrap file will route the request to a specific controller, creating dependencies along the way.
Using parent::__construct() is perfectly fine, it's how you will actually pass the objects dependencies. However, you can question why you need it. I don't see why your Controller should extend a core Controller. They actually don't always have the same dependencies, making it harder to manage if you make them all inherit from a base class.
I think you are confusing Dependency Injection and extending classes.
Dependency injection handles external dependencies for a class. This means that if you use one class in another class (using class A in class B, not extending class A) it's a dependency. The dependency container will create the instances automatically and hand them over to the class which needs them.
Further reading here.
When I first saw dependency injection components like PHP-DI, Symfony2 DI, etc., I though, there is a way to automatically inject instance of any class to any just with one instantiation.
So
1. Create instance in root class like $foo = new Foo()
2. And then I can use this instance in any object (like global singleton) without passing reference to constructor or method of the class I want to call from.
But I found out, that basicly I can use Dependency Injection in 2 ways
1. Passing the reference of the instance to constructor
2. Creating container where all objects are located. This container could be injected to other classes, but "This is not recommended".
As both ways can be easily done in pure PHP, the first is clear, the second could be solved with static properties, so why to use PHP-DI or Symfony2 for this work?
Why should you use Dependency Injection over the Singleton pattern?
Let's assume we have a Singleton object named DatabaseConnection which wraps a connection to a MySQL database for us and does some other neat things, who knows. Because reusing code is a good thing, we use this object in a lot of projects.
What if at some point we decide to switch one of our projects from MySQL to another database product? We would have to modify every place where we call the DatabaseConnection object and replace it with our new implementation. Or, we could modify the class itself -- but we still want to use the original one with other projects, so we end up with two implementations with the same name which is just asking for trouble, really.
And what about unit tests? We do those, of course, because we are good developers! But if we unit test a function that uses the database, we don't want the test to actually rely on the database or even change things there. There's no way to replace the DatabaseConnection with a mock object (that just returns static data) because our project is tightly coupled to it.
That's what Dependency Injection does: It helps to prevent tight coupling. If we inject the connection with $someObject->setDatabaseConnection($databaseConnection), we can inject any object there that behaves like the original one. We can inject mock objects, alternative implementations or extensions that inherit the original class.
Now a Dependency Injection Container is just a nice helper to manage object instances and their dependencies more easily, but it's not needed for doing Dependency Injection.
I am starting using Behat and I was thinking what is the correct way to do something like this:
I am testing system behaviour with Behat (the domain, not web) and i want to test behaviour that uses UserService class. UserService takes UserRepository (Interface) as an argument. Should i create the UserService object in the context or should i take it from some dependency injection container (which i currently don't have since i want to model the domain first)? Or should i maybe create a factory to construct the UserService? Should I mock those dependencies?
The problem here is, that there may be multiple implementations of UserRepository and i want to test the one the system uses (hence taking UserService from DI container). I do not know which implementation i am going to use at the time of writing the feature file/context. Probably just some dummy FilesystemUserRepository just to pass the tests.
If I used the FilesystemUserRepository in contexts, then after i decide to move to DatabaseUserRepository later in development i would have to rewrite all the contexts that use UserService class.
Is there some best practice how to do this?
I usually start with creating everything in my context's constructor, as it's a phase I move back and forward a lot and I don't want to be distracted by having to create service definitions. At this phase code might change a lot, so it would be rather inefficient anyway.
Later on, I create service definitions in the application's container. With the Symfony container it is very easy to inject those services directly into your context. Another advantage is that with Symfony environments you can actually replace some services in test environment. I actually use this a lot, as I prefer to use in-memory repositories in acceptance tests, rather than those based on a database.
On some projects I didn't take the second step, and left all the service initialization in Behat's context class. It worked well too.
My understanding:
A dependency is when an instance of ClassA requires an instance of ClassB to instantiate a new instance of ClassA.
A dependency injection is when ClassA is passed an instance of ClassB, either through a parameter in ClassA's constructor or through a set~DependencyNameHere~(~DependencyNameHere~ $param) function. (This is one of the areas I'm not completely certain on).
An IoC container is a singleton Class(can only have 1 instance instantiated at any given time) where the specific way of instantiating objects of those class for this project can be registered. Here's a link to an example of what I'm trying to describe along with the class definition for the IoC container I've been using
So at this point is where I start trying use the IoC container for more complicated scenarios. As of now it seems in order to use the IoC container, I am limited to a has-a relationship for pretty much any class I want to create that has dependencies it wants to define in the IoC container. What if I want to create a class that inherits a class, but only if the parent class has been created in a specific way it was registered in the IoC container.
So for example: I want to create a child class of mysqli, but I want to register this class in the IoC container to only instantiate with the parent class constructed in a way I've previously registered in the IoC container. I cannot think of a way to do this without duplicating code (and since this is a learning project I'm trying to keep it as 'pure' as possible). Here are some more examples of what I am trying to describe.
So here are some of my questions:
Is what I'm trying to do above possible without breaking some principle of OOP? I know in c++ I could use dynamic memory and a copy constructor to accomplish it, but I haven't been able to find that sort of functionality in php. (I will admit that I have very little experience using any of the other magic methods besides __construct, but from reading and __clone if I understood correctly, I couldn't use in the constructor it to make the child class being instantiated a clone of an instance of the parent class).
Where should all my dependency class definitions go in relation to the IoC? (Should my IoC.php just have a bunch of require_once('dependencyClassDefinition.php') at the top? My gut reaction is that there is a better way, but I haven't come up with one yet)
What file should I be registering my objects in? Currently doing all the calls to IoC::register() in the IoC.php file after the class definition.
Do I need to register a dependency in the IoC before I register a class that needs that dependency? Since I'm not invoking the anonymous function until I actually instantiate an object registered in the IoC, I'm guessing not, but its still a concern.
Is there anything else I'm overlooking that I should be doing or using? I'm trying to take it one step at a time, but I also don't want to know that my code will be reusable and, most importantly, that somebody who knows nothing about my project can read it and understand it.
Put simply (because it's not a problem limited to OOP world only), a dependency is a situation where component A needs (depends on) component B to do the stuff it's supposed to do. The word is also used to describe the depended-on component in this scenario. To put this in OOP/PHP terms, consider the following example with the obligatory car analogy:
class Car {
public function start() {
$engine = new Engine();
$engine->vroom();
}
}
Car depends on Engine. Engine is Car's dependency. This piece of code is pretty bad though, because:
the dependency is implicit; you don't know it's there until you inspect the Car's code
the classes are tightly coupled; you can't substitute the Engine with MockEngine for testing purposes or TurboEngine that extends the original one without modifying the Car.
It looks kind of silly for a car to be able to build an engine for itself, doesn't it?
Dependency injection is a way of solving all these problems by making the fact that Car needs Engine explicit and explicitly providing it with one:
class Car {
protected $engine;
public function __construct(Engine $engine) {
$this->engine = $engine;
}
public function start() {
$this->engine->vroom();
}
}
$engine = new SuperDuperTurboEnginePlus(); // a subclass of Engine
$car = new Car($engine);
The above is an example of constructor injection, in which the dependency (the depended-on object) is provided to the dependent (consumer) through the class constructor. Another way would be exposing a setEngine method in the Car class and using it to inject an instance of Engine. This is known as setter injection and is useful mostly for dependencies that are supposed to be swapped at run-time.
Any non-trivial project consists of a bunch of interdependent components and it gets easy to lose track on what gets injected where pretty quickly. A dependency injection container is an object that knows how to instantiate and configure other objects, knows what their relationship with other objects in the project are and does the dependency injection for you. This lets you centralize the management of all your project's (inter)dependencies and, more importantly, makes it possible to change/mock one or more of them without having to edit a bunch of places in your code.
Let's ditch the car analogy and look at what OP's trying to achieve as an example. Let's say we have a Database object depending on mysqli object. Let's say we want to use a really primitive dependency indection container class DIC that exposes two methods: register($name, $callback) to register a way of creating an object under the given name and resolve($name) to get the object from that name. Our container setup would look something like this:
$dic = new DIC();
$dic->register('mysqli', function() {
return new mysqli('somehost','username','password');
});
$dic->register('database', function() use($dic) {
return new Database($dic->resolve('mysqli'));
});
Notice we're telling our container to grab an instance of mysqli from itself to assemble an instance of Database. Then to get a Database instance with its dependency automatically injected, we would simply:
$database = $dic->resolve('database');
That's the gist of it. A somewhat more sophisticated but still relatively simple and easy to grasp PHP DI/IoC container is Pimple. Check its documentation for more examples.
Regarding OP's code and questions:
Don't use static class or a singleton for your container (or for anything else for that matter); they're both evil. Check out Pimple instead.
Decide whether you want your mysqliWrapper class extend mysql or depend on it.
By calling IoC from within mysqliWrapper you're swapping one dependency for another. Your objects shouldn't be aware of or use the container; otherwise it's not DIC anymore it's Service Locator (anti)pattern.
You don't need to require a class file before registering it in the container since you don't know if you're going to use an object of that class at all. Do all your container setup in one place. If you don't use an autoloader, you can require inside the anonymous function you register with the container.
Additional resources:
Inversion of Control Containers and the Dependency Injection pattern by Martin Fowler
Don't look for things -- a Clean Code Talk about IoC/DI