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.
Related
I am looking for a php implementation or a design pattern something like this (just a very basic skeleton example):
namespace Contract {
interface Application {...}
interface EntryPoint {...}
}
namespace RestApi {
class Module {
/** #return Contract\EntryPoint */
public function getEntryPoint(Contract\Application $application){...}
}
class EntryPoint implements Contract\EntryPoint {...}
}
namespace BusinessLogic {
class Module {
/** #return Contract\Application */
public function getApplication(){...}
}
class Application implements Contract\Application {...}
}
$dependencyResolver = new DependencyResolver();
$dependencyResolver->parse(new RestApi\Module());
$dependencyResolver->parse(new BusinessLogic\Module());
$dependencyResolver->invoke(function (Contract\EntryPoint $entryPoint){
$entrypoint->handleRequest();
});
I want to loose couple every modules I am using in my application, so I intend to design interfaces, maybe abstract classes with validation to make a well defined interface for every module type. I haven't found a solution for this problem, ppl usually inject things with IoC container, which does not tell anything about the common interface between two modules...
Do you know a design pattern which solves this problem, or a de factor standard php implementation/framework for this?
note: IoC container is not a solution, I want to inject the dependencies with well defined interfaces, not to pull them from a DI container or service locator... I don't want my modules to know anything about how they get their dependencies...
edit:
I updated my question because I don't think my code was obvious for everyone. A created a class diagram to ease the understanding of it:
Okay, so this diagram contains a description of a single environment. We usually use different environments for example: test, development, production, etc... Each of these environment contains different modules, for example by testing and developing we usually turn off email sending, so one of the modules contains a mock php mailer in those environments... As you see by cross-module dependency the classes depend on contracts, not directly on each other. This way the code of the modules is loose coupled...
I intend to describe this dependencies (for example with annotations) and inject them on an automated way somehow. This is a difficult task, because by PHP I have to load only the classes which are necessary to handle the request. For example:
So I have to use lazy load somehow, for example I could inject factories, but I don't like that idea, I want to inject the dependency itself, not a factory...
Be aware that the contract interface does not know anything about its implementations, so I have to publish somehow those implementations by every module and find them from the other modules... Most of the DI container implementations solve that problem, but I don't want to inject factories or DI containers into my modules. I want them to depend on the contracts only and nothing else...
Matthieu Napoli recommended to use just a single IoC container with different config by each of the environments, but I don't see how this would solve my problem. That DI container would instantiate every class with cross-module dependency, so I would move the whole config of every modules into a huge main config file. Even by a simple project I'd have about 20 classes (languages, users, identification-factors, user-identification-factors, contacts, user-contacts, roles, user-roles, permissions, role-permissions, articles, comments, etc...) and at least 3 modules (presentation layer, business logic layer, data access layer). So that main config would contain the instantiation of at least 60 classes from different modules... That would be pretty hard to maintain and I am almost certain that it would result a lot of code repetition by configs of different environments... Yes maybe splitting the config files can reduce the pain, but I guess I wont know the advantages and drawbacks of this solution until I start to use it on a complicated project. Another problem with this approach that how should I implement the lazy load without injecting the IoC container itself into every class with cross-module dependency? I think I need proof or example code, that this approach really works well by this problem domain...
Currently I am thinking on something similar than require.js does with AMD javascript modules, but that injects the IoC container as well by lazy load. You have to use the require("moduleName") from inside the modules if you want to load a dependency which you don't want to use in your code, just in case when it's really necessary. Ofc that require is just a sugar syntax of container.get("moduleName")... Currently I don't see how to solve that problem. I think every of my modules should have one or more DI containers, call them module containers. Those module containers can handle the cross-module dependencies. By lazy load the module containers would pull down the cross-module dependencies of each class from a main container, which would automatically register every module container and every class instantiated by them. In this scenario only the module containers would know about the main container if I cannot solve lazy load without injecting a factory or a DI container or a service locator... Ofc this is the last resort, I think I can do the lazy load somehow without injecting the main container into the module containers. Or at least I can do it somehow with a sugar syntax, for example:
class ModuleContainer {
public function setCrossDomainDependency(Contract\Dep $crossDomainDependency){
//...
}
/** #return Contract\Dep */
public function getCrossDomainDependency(){
//...
}
}
My purpose to use the same ModuleContainer instance regardless of having a MainContainer. I'll check the reflection api, maybe I am able to override the getCrossDomainDependency somehow at runtime. If not then I think the only solution to inject factories or the main container... Nah but this is my solution...
How would you solve this problem?
A IoC container is exactly the solution.
I want to inject the dependencies with well defined interfaces, not to pull them from a DI container or service locator
Then don't use the container as a service locator. That's exactly what a DI container is meant for.
Here is your example using PHP-DI:
$containerBuilder = new ContainerBuilder();
$container = containerBuilder->build();
// Configure RestApi\EntryPoint to use for Contract\EntryPoint
$container->set(Contract\EntryPoint::class, \DI\link(RestApi\EntryPoint::class));
// Configure BusinessLogic\Application to use for Contract\Application
$container->set(Contract\Application::class, \DI\link(BusinessLogic\Application::class));
// Run
$entryPoint = $container->get(Contract\EntryPoint::class);
$entryPoint->handleRequest();
Of course my example here is not perfect. I would suggest to separate the configuration part from the execution part. I would put the configuration in a configuration file (look here for how).
Important: Yes, in that example I fetch something from the container. That is exceptional. That should happen only once or twice in your application.
You have to use the container at some point, at the root of your application (i.e. the entry point of the app), to construct the object graph (or dependency graph).
I am not suggesting that you call get() on the container everytime you need a dependency. I am suggesting that you use dependency injection instead, and that you call get() only at the entry point of the application.
Example of defining with a factory:
$container->set(Contract\EntryPoint::class, \DI\factory(function (Container $c) {
return new RestApi\EntryPoint($c->get('some.parameter'));
}));
I have read the service container chapter in the Symfony2 book multiple times and read SO answers and other resources regarding the topic, but I still just don't seem to get it.
So far, everything I've read has drilled one main truth into my head: the container itself should (practically) never be directly injected into a dependent. This seems to work fine for providing dependencies to other services, but what if an entity in my model wants to inspect the current security context, for instance?
I'm aware that I can implement ContainerAwareInterface and then call setContainer() from a container-aware context to gain access to the container itself in this case, but isn't this the same as injecting the container from the service configuration which is to be avoided at all costs?
What you describe is just bad design. Your model shouldn't be dependent on the service container. If you need to perform some security checks then you would create a service that has the necessary dependencies injected to it and then pass your model objects to it.
By your example it sounds like you're trying to do validation which is described here http://symfony.com/doc/master/book/validation.html and works much like I stated.
Recently i moved to Symfony 2 and i have a litte question.
Let's say i have the following Model:
"catalog" which contains "catalogs". The model gets its data from files but also needs a database connection to verify things.
In the Zend framework or other past projects i loaded the dependencies by a static object which forms a kind of "registry".
As i understand, Symfony 2 uses their service pattern (dependencie injection) instead. But how does this apply to my case.
Must i create a service for every model class i use to auto inject all dependencies? Or is it perfectly valid when i create a instance from my object myself and set for example the database connection in my constructor?
To create a service for every class which needs dependencies, seems a little bit overkill to me.
You can certainly create classes and inject dependencies the old-fashion way but take the time to learn the details of creating services. I think you will find:
Adding a new service is trivial. Copy/paste a few lines of configuration, adjust the class, id and maybe some parameters and you are done. Takes much less time than creating the actual class.
Very soon you will progress from just injecting a database connection to injecting other services as well as perhaps some parameters. Do you really want to have to remember to do all that stuff each time you need to new an object?
Using service id's can divorce your controllers from the exact location/name of a class. The first time you need to do some refactoring and maybe move some services into their own bundle or perhaps swap out a service with another you will be glad that you won't need to hunt down all your code and make changes.
S2 is not really focused on "Models". Instead, think in terms of a service named CatalogManager which wraps access to assorted catalog functionality.
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
I'd like to:
Make commonly required services visible to all classes that need them,
with a minimum of boilerplate, and
without sacrificing testability!
It's a small project and I think DI might be overkill, but maybe I'm wrong? Anyhow, I have been focusing on the ServiceLocator pattern as described by Martin Fowler
In a client class' constructor, I have something like this:
this->db = Locator::getDb();
this->log = Locator::getLogger();
Then the rest of the class' methods access the service through those member attributes, e.g.:
this->fooModel = new fooModel(this->db);
fooItem1234 = this->fooModel->findById(1234);
However I would also like this level of visibility for "model" objects (like fooModel above) because they are accessed from several different places and there is no need to have more than one instance.
So my initial thought was to extend Locator to have a ::getFooModel() but now it seems I'm violating the Open/Closed Principle, since I'll have to modify Locator every time I introduce a new model class.
To satisfy OCP, I could use the Dynamic Service Locator (also described on Fowler's page) however I'm not totally sold on this for the same reasons as him, i.e. it's not explicit enough.
Another solution would be to just make all my models' methods static. So:
fooItem1234 = FooModel::findById(1234);
I like this because it's zero boilerplate. I can just create a new model class and start calling it from anywhere with a single line. But now the model depends on Locator to find its DB connection and I'm not sure how I feel about that. For one, if I ever needed to have two fooModels open on separate database connections, it would be a mess and/or impossible. That said, I don't actually need to do that currently so this option seems a little tempting.
Finally, there's DI. But like I said above I think it might be too much for this little project.
Conclusion: I'm a little stuck here and would appreciate some advice from the gurus of StackOverflow!
Why do you think that DI is overkill for your project? DI patterns such as Constructor Injection is way simpler and cleaner than Service Locator (which I consider an anti-pattern).
I consider Service Locator to be an anti-pattern since it is totally opaque to the user of the API which dependencies need to be in place; thus, one could easily invoke methods on your objects in a context where the Service Locator would throw, and the API gives you absolutely no clue that this is the case.
You don't need a DI Container to use DI. If just have a simple project, you can use what is known as Poor Man's DI where you wire up dependencies manually.
... and there is no need to have more than one instance.
You're mixing apples and oranges. The fact that you only need one instance of a class for an application, is not the same thing as it being a good idea to make that instance globally available. With DI you don't change the cardinality - there is still just one instance. What you change is the scope of variables that address said instance. There's a difference.