Ok, so I think that I have a basic understanding of IoC and the patterns relating to it, dependency injection and the service locator pattern.
From what I have read it seems that dependency injection into a class constructor is more favourable for loose coupling that the service locator.
What I am having trouble understanding, and can’t really find anything written about it, is what to do if I want to instantiate an object from a high level class? Do I have the change the constructor for the class which is calling the new class? If so, that would mean that I would have to change the every call to that constructor and the constructors of every class making that call, and so to the root. This seems very cumbersome and unsafe. Would a service locator be more appropriate in this scenario?
Any advice would be appreciated.
Simple example:
class car
void car(iBrand brand, iModel model){
_brand=brand;
_model=model;
}
class brand : iBrand
void brand (iModel model){
_model=model;
}
class model : iModel
void model()
This is a particularly crude example but hopefully should get my point across. each of these objects instantiates the class below. Now if I want to create an iEngine in the model class, does this mean it has to be passed all the way down from the top, including into the car constructor?
class car
void car(iBrand brand, iModel model, iEngine engine){
_brand=brand;
_model=model;
_engine=engine;
}
Thanks,
H
There should be only one place in your application that is instantiating injectable classes; the Composition Root. So there should be nobody but the Composition Root who is calling the components' constructors. It should be the Composition Root who composes the object graphs.
A dependency should only be included in the constructor of a type, if that type uses that dependency directly. In your example both Brand and Car depend on IModel, but if Car doesn't need to interact with IModel directly, model should not be injected into Car. Or imagine a UsersController class that depends on an IUserRepository. If the UserRepository needs to be extended with some logging, the UsersController should not have to know about this. You should just inject an ILogger into the UserRepository's constructor and the UsersController stays unaffected.
Since the Composition Root is the only place that calls the constructor, and adding dependencies should not ripple through the whole dependency graph, changing a constructor should mean that only the Composition Root is affected (besides the class in question of course). And if you use a DI framework, you will in most cases even prevent having to change anything at all.
Related
Based on this question, THE way to initialize new object with runtime parameters when using ioc-container is to create Abstract Factory.
In my example, I have this class:
internal sealed class AssetsDownloadingProcess
{
private readonly IBackgroundWorker _backgroundWorker;
private readonly IAssetsStorage _assetsStorage;
private readonly Parameters _parameters;
public AssetsDownloadingProcess(IBackgroundWorker backgroundWorker,
IAssetsStorage assetsStorage, Parameters parameters)
{
_parameters = parameters.Clone();
_backgroundWorker = backgroundWorker;
_assetsStorage = assetsStorage;
}
}
And a factory to construct it:
internal sealed class AssetsDownloadingProcessFactory
{
private readonly IBackgroundWorker _backgroundWorker;
private readonly IAssetsStorage _assetsStorage;
public AssetsDownloadingProcessFactory(IBackgroundWorker backgroundWorker,
IAssetsStorage assetsStorage)
{
_backgroundWorker = backgroundWorker;
_assetsStorage = assetsStorage;
}
public AssetsDownloadingProcess CreateProcess(
AssetsDownloadingProcess.Parameters parameters)
{
return new AssetsDownloadingProcess(
_backgroundWorker, _assetsStorage, parameters);
}
}
as you can see, AssetsDownloadingProcess does not implement any interface and will never be replaced with another class. Therefore this factory is nothing more than useless piece of code. It could be completely omitted in favour of AssetsDownloadingProcessFactory constructor. However, then I can't use dependency injection to constructor.
I would like to use benefits of Injection from my IoC Container without the hassle of creating factory and creating useless code. What is the correct way to do this? Am I missing something or using DI wrong?
In general, you should prevent using runtime data to create and initialize your application components, as described here. The mere fact that runtime data is passed in through the constructor forces you to create a Factory.
The solution given by the article to the problem of injecting runtime data into components is to let runtime data flow through method calls on an initialized object graph by either:
pass runtime data through method calls of the API, or
retrieve runtime data from specific abstractions that allow resolving runtime data.
When runtime data is not used during object graph construction, the component can be created using DI inside the Composition Root and you problem therefore goes away.
Doing so however is not always feasible, and when it isn't, an Abstract Factory is the solution.
Since Object Composition should solely take place in the application's Composition Root however, this means that your Abstract Factory must be an Abstraction. Only this way can you prevent that the construction of your AssetsDownloadingProcess component takes place inside the Composition Root.
The way to do this is to:
Define an abstraction, i.e. IAssetsDownloadingProcessFactory in the application layer where the consumers of this factory live.
Create an implementation of this abstraction inside the Composition Root.
Not using an abstraction means that consumers will take a dependency on the concrete AssetsDownloadingProcessFactory class (which is a Dependency Inversion Principle violation) and it pulls the object composition out of the Composition Root. This will cause object composition to be scattered throughout the application, which hinders maintainability.
I'm having troubles getting the advantage of a IoC (DI) container like Ninject, Unity or whatever. I understand the concepts as follows:
DI: Injecting a dependency into the class that requires it (preferably via constructor injection). I totally see why the less tight coupling is a good thing.
public MyClass{
ISomeService svc;
public MyClass(ISomeService svc){
svc = svc;
}
public doSomething(){
svc.doSomething();
}
}
Service Locator: When a "container" is used directly inside the class that requires a dependancy, to resolve the dependancy. I do get the point that this generates another dependancy and I also see that basically nothing is getting injected.
public MyClass{
public MyClass(){}
public doSomething(){
ServiceLocator.resolve<ISomeService>().doSomething();
}
}
Now, what confuses me is the concept of a "DI container". To me, it looks exactly like a service locator which - as far as I read - should only be used in the entry point / startup method of an application to register and resolve the dependancies and inject them into the constructors of other classes - and not within a concrete class that needs the dependancy (probably for the same reason why Service locators are considered "bad")
What is the purpose of using the container when I could just create the dependancy and pass it to the constructor?
public void main(){
DIContainer.register<ISomeService>(new SomeService());
// ...
var myclass = new MyClass(DIContainer.resolve<ISomeService>());
myclass.doSomething();
}
Does it really make sense to pass all the dependancies to all classes in the application initialization method? There might be 100 dependancies which will be eventually needed (or not) and just because it's considered a good practice you set create them in the init method?
What is the purpose of using the container when I could just create the dependancy and pass it to the constructor?
DI containers are supposed to help you create an object graph quickly. You just tell it which concrete implementations you want to use for which abstractions (the registration phase), and then it can create any objects you want want (resolve phase).
If you create the dependencies and pass them to the constructor (in the application initialization code), then you are actually doing Pure DI.
I would argue that Pure DI is a better approach in many cases. See my article here
Does it really make sense to pass all the dependancies to all classes in the application initialization method? There might be 100 dependancies which will be eventually needed (or not) and just because it's considered a good practice you set create them in the init method?
I would say yes. You should create the object graph when your application starts up. This is called the composition root.
If you need to create objects after your application has started then you should use factories (mainly abstract factories). And such factories will be created with the other objects in the composition roots.
Your classes shouldn't do much in the constructor, this will make the cost of creating all the dependencies at the composition root low.
However, I would say that it is OK to create some types of objects using the new keyword in special cases. Like when the object is a simple Data Transfer Object (DTO)
I have been looking for a while on the Internet about this but could not find an exact answer. Okay, they say inject an abstraction (interface or something) to a class rather than having it to create the instances it needs, or rather than passing an implementing type.
class Foo
{
private IBar _bar;
public Foo(Ibar bar)
{
_bar = bar;
}
}
Although I don't fully understand how above is reasonably loosely coupled, but my question at this point is about something else. That is, what if a method has to return an instance of something. How, for example, following can be made loosely coupled:
class Foo
{
public IBar GetMeSomething()
{
return new Bar(); // dependency here
}
}
I was just wondering how I resolve the above dependency on Bar? Any experienced programmers please help me understanding this. Or someone may be able to suggest some article comprehensively discussing all such scenarios that eliminate/reduce type inter-dependencies.
When a class need to know "Something" about your program, you can resolve that by passing a instance of another class in your constructor.
If you accept in constructors only interfaces instead of concrete classes you are later able to change implementation easily.
If you have to create Objects at run time you need factories, you class Foo is in your case a IBarFactory (because it instantiate IBars).
Dependencies in constructors via interfaces are easily resolved by any IoC framework (Factories are passed in constructors too), while the implementation of a factory itself is allowed to instantiate objects directly or through a IoC framework because that's the responsability of the class.
Using IoC containers and dependency injection does not make looscoupling happens for magic, you still have to model classes with SOLID principles in mind, but when using SOLID principles IoC containers and DI are of great help.
I'm simply looking for advice on the best way I should handle this situation.
Right now I've got several files in a folder called Service. The files contact several functions which do random things of course. Each of these files needs access to the SM Adapter.
My question is, should I implement the ServiceManagerAwareInterface in each of these files OR should I just make a new class which implements the ServiceManagerAwareInterface and just extend my classes on the new class which implements this service?
Both ways work as they should, just not sure which way would be more proper.
If you think that your system will always rely on ZF2, both approaches are equivalent.
Now from an OO design perspective, personally I have a preference for the approach in which you extend your service then implement the ServiceManagerAwareInterface. I would even use an interface for the dependency over the ServiceLocator to protect even more my classes. Why?
Extending your classes does not cost you a lot, same for making your class depending on interfaces.
Let's take this example, Imagine you did not use this approach during a ZF1 project, during which you had probably resolved your dependencies with the Zend_Registry.
Now, let's assume you moved to a ZF2 implementation, how much time you think you'll spend refactoring your code from something like Zend_Registry::get($serviceX) to $this->getServiceManager()->get($serviceX) on your Service layer?
Now Assume you had made the choice of protecting your classes, first by creating your own Service locator interface, as simple as:
public interface MyOwnServiceLocatorInterface{
public function get($service);
}
Under ZF1 you had created an adapter class using the Zend_Registry:
public class MyZF1ServiceLocator implements MyOwnServiceLocatorInterface{
public function get($service){
Zend_Registry::get($service);
}
}
Your Service classes are not coupled to the Zend_Registry, which make the refactoring much more easier.
Now, You decide to move to ZF2 so you'll logically use the ServiceManger. You create then this new Adapter class:
public class MyZF2ServiceLocator implements
ServiceManagerAwareInterface,MyOwnServiceLocatorInterface
{
private $_sm;
public function get($service){
$this->_sm->get($service);
}
public function setServiceManager($serviceManager){
$this->_sm = $serviceManager;
}
}
Again, your Service classes are not coupled to the ZF2 ServiceManger.
Now, how would look like the configuration/registration of you Service layer on the ServiceManager. Well, you'll use your Module::getServiceConfig class for that:
//Module.php
public function getServiceConfig()
{
return array(
'factories'=>array(
'My\ServiceA'=>function($sm){
return new My\ServiceA($sm->get('My\Service\Name\Space\MyZF2ServiceLocator'));
}
//Some other config
)
}
As you can see, no refactoring is needed within your Service classes as we protected them by relying on interface and using adapters. As we used a closure factory, we don't even need to extend our Service classes and implement the ServiceLocatorAwareInterface.
Now, before concluding in my previous example i have to note that I did not treat the case in which my classes are constructed via factories, however, you can check one of my previous answers that address the factory topic but also the importance of loose coupling among an application layers.
you can add initializers to do that. It can reduce repetitive injection in getting the service that pass db adapter. OR, you can set abstract_factories, it will reduce repetitive SM registration. I just posted SM Cheatsheet here, Hope helpful :)
https://samsonasik.wordpress.com/2013/01/02/zend-framework-2-cheat-sheet-service-manager/
I spent lot of time in understanding ioc. I never understand how exactly control is inverted in this pattern. Even I am confused with exact meaning of inversion. In normal english - inversion is some thing like reversing, say reversing a cup.
If I consider dependency injection as Ioc. I would like to know where exactly contol is inverted here. I understand here in DI, dependency is inserted from an external entity with the help of constructor, setter ........
But I never understand where the control is inverted here...
Any help appreciated.
Old style:
Class car
{
Engine _engine;
Public Car()
{
_engine = new V6();
}
}
inverted:
Class car
{
Engine _engine;
Public Car(Engine engine)
{
_engine = engine;
}
}
var car = new Car(new V4());
The caller has the control instead of the car class
Dependency injection inverses control.
For example a car class needs a engine class. The engine could be any type of engine.
If you don't use DI, the car class would determine the engine type itself, the car class is in control.
When using DI, the code instantiating a car would determine the type of car (by specifying the engine in constructor for example), the calling code is now in control. Control is inverted from car class to calling code.
To expand on robin's answer:
IUserRepository _user = new UserRepository();
//you're in control of which instance is created.
With dependency injection:
IUserRepository _user;// you will not do anything else.
Based on a configuration somewhere else, the dependency injection framework you use will take care of creating the right instance for you. This is when control is inversed from your code. You are not directly creating any instance from your code.
Why!? Why would you do this?
One major advantage is testing, when you run tests, you can configure your IUserRepository with a fake one.