IoC in Domain Layer - php

In my Domain layer I have contract Hashing. One of my domain services depends on this contract. At the moment I have injected it within a __construct method.
In infrastructure layer I have implementation of this contract. I have written something looks like IoC container, which creates services with auto wiring injecting.
It all works. But I know that service's dependencies will grow up. I will add much more UseCases to them. And there is another one problem -- container injects all dependencies, but we could use only one UseCase, so it will do excess job.
Is it ok, if I will inject IoC container itself instead of many parameters, and use it in UseCases.
IoC contract also lies in Domain Layer contracts namespace

Is it ok, if I will inject IoC container itself instead of many parameters
No, it is not okay. Supplying any class outside your Composition Root with access to an unbounded set of dependencies is considered an anti-pattern. This anti-pattern is called Service Locator.
Injecting the container causes the class to take a dependency on a redundant component (the container) and makes it non-obvious what the class's dependencies are. This complicates testing and makes the class dishonest about its level of complexity.
You might be tempted to inject the container to prevent the class's constructor from keep changing, but this is a sign of another problem. Classes that keep getting new dependencies likely violate the Single Responsibility Principle. You will end up with classes with many constructor arguments—a code smell called Constructor over-injection.

Related

How to use Auryn for DI in the "right" way?

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.

Testing behaviour of classes with deep nested dependencies

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.

SoftwareArchitecture: Service Dependency - Inject Container or concret class

Assume the following Service classes:
class A {}
class B {}
class C {}
Now Class A gets a dependency on Class B. So i just inject Class B.
Later in the development my Class A needs Class C too.
(This could go on and on...)
Is it better to inject the Dependency Container to be able to use all services as needed. Or keep the service classes small by only injecting those classes i need?
Whats the best practice here, and why?
Currently i tend to inject each dependent service i need, mainly to see the dependency in one place (the DI annotation in the header).
Please don't close as "opinion based" this questions is for best
Practice, this have to be a opinion, but when a majority of users have
the same opinion then its a best practice.
I advise against injecting whole service container. If you do so, class dependencies get blurry (eg. you have to go through whole class code to see what dependencies this class needs) and it may lead to a mess.
Inject these dependencies you need directly. If you noticed that there are a lot dependencies in your class, it should be an alert for you that this class is doing too much (or have too many responsibilities) and you should split it (or separate responsibilities).
Don't inject the container. This is the service locator pattern, and it is usually looked at as an anti-pattern.
Reasons:
injecting the container couples your code to the container, which is bad because if you want to change the container you use, you have lots of classes that needs to be changed
it also hides the dependencies your class needs: dependencies are no longer explicit. Say I want to use your class, how do I know which dependencies I need to set in the container for your class to work?
what happens if you inject the container, and then your class gets a dependency but the dependency doesn't exist: exception
This is not just an opinion, there are good reasons justifying dependency injection over service location.
Injecting concrete classes is contradictory to Dependency Inversion Principle (DIP). In you case, class A (relatively higher class) should not depend on class B (relatively lower class); both should depend on an abstraction instead. So, the abstract class or an interface which is inherited or implemented by class B, should be injected into class A. The same is true for class A and class C.
IMHO, injecting the whole Dependency Container introduces an extra overhead to the injected class. So the class should be injected with those abstractions only as needed. In order to achieve that, it is also needed to design the class accordingly from the very beginning.

PHP Factory Pattern Dependency Injection

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

How to access services inside non-controller function in Symfony 2

You may access the (let's say) Doctrine service inside the controller, using:
$d = $this->getDoctrine()
now I want my controller to call another function (in another class) and I want that class to have access to all services. Is that possible without passing the services as variable?
You have to inject dependent services to your class or method. If you were thinking about some global object you might access everywhere than it's not the right way to go (and you can't actually access the container this way). You'd miss the whole point of dependency injection.
You can inject the services to your class two ways:
Manually
Let DIC do it
First solution requires you to pass the dependency yourself either way (constructor, setter, method).
The later solution means you define your class as a service and let container construct it and inject the dependencies. It can only be done if you can delegate object creation to DIC. It cannot be done with Entities for example.
Be careful with injecting whole container. It's not the best practice. You'd introduce dependency on a whole container which might have different services depending on the configuration. Dependencies wouldn't be clear.

Categories