I got a huge Symfony project. I created many service and subservices to epurate the Controller and Services code.
In my code i instantiate these services with:
$this->get('MyServiceName')->myMethod($foo);
One of my coworker use the new keyword to instantiate the class:
$myservice = new Service();
$refid = $myservice->mymethod($foo);
So i wondering, is it a best practice? Should i rewrite that codeĀ ? What are the impact of this kind of code on the maintenability and the performance of the application?
If the service is defined in the Ioc container, then by all means use it from there, because it will be constructed by the container. It takes the responsibility of instantiating new classes away from the developer. If the explicit dependencies change, you will only need to change them in container, not hunt them in the whole project code. This also in most cases has the performance benefit, because some classes need to be instantiated only once. In any way, talk to your co-worker, why he does it like this.
I always use the first way (ie. using the service container) because with Symfony's dependency injection you don't need to worry about dependecies and/or parameters; I've never used the second way (ie. instantiating a service "by hand" with the new keyword) and I'm pretty sure that it is the worst way.
By the way, you should check out the official "best practices" guide and these blog posts by Fabien Potencier.
Related
I'm currently using Laravel and have a pretty good general grasp now on how the dependency injection and service container works now. I see it working very well when programming to interfaces, but what about concrete classes?
I utilize a service layer between my controllers and models. The point of the service objects was so that I could easily reuse their methods elsewhere, like in a different controller. But there are cases where I also need to use a service inside another service.
So I've been using the constructor for the dependency injection inside my services. The issue I kind of see is that sometimes I only need a service (inside one of my other services) for 1 method. So doing it in the constructor makes it rather large. On the other hand, since I've been setting these parameters in the constructor, I can't simply new-up an instance on demand, since it requires those parameters. For example, let's say I have an OrderService class, and for the constructor, I see two ways I can go about it:
public function __construct(FileUploadService $fileUploadService)
{
$this->fileUploadService = $fileUploadService;
}
or
public function __construct()
{
$this->fileUploadService = new FileUploadService;
}
I've mostly been doing it the first way, but have been thinking about the second. If I ever needed this OrderService somewhere else in the app, I can't simply create a new instance since it relies on the FileUploadService, unless I create a new instance of that too. But you can see that it will start to cascade without the dependency injection, because what if the FileUploadService depends on something also? It's just easier to resolve it out of the container.
Maybe there's something I'm missing, because it almost feels like a catch 22 in some ways. I'd like to note that a majority of these classes I'm injecting are concrete classes, so I don't need to swap them out at any particular point.
I've thought about just creating a new instance in the constructors for each service I need, that way I can also new-up the instance without providing parameters. But I like to follow best practices, so I was wondering what other experienced developers thought about this.
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.
After reading a trillion vague tutorials on Dependency Injection Containers, I feel as though I'm still not fully getting the point.
When it comes to things that are application specific (like models, controllers, etc), how should I manage the auto-injection of dependencies?
I happen to have a LARGE website, with maybe 30-40 different types of models...do I really create a single application dependency manager to handle each of these different types?
I have had people tell me that DIC's are not meant for domain stuff, but more for framework stuff, and I have also heard the opposite.
Which is "right"?
BONUS QUESTION:
If DIC's aren't applicable for domain layer objects (like models), how do you pass dependencies to the domain layer objects?
Maybe not exactly what you are looking for but here is an example usage of Dependency Injection Container (DIC)
Let's say I have a Database class and a Cache class. I need to be able to access my database and my Cache class inside of my other classes (models, controllers, etc).
This is a situation where a DIC would come in handy, I can simply store my Database and Cache class inside the DIC class and pass that DIC class into any other class that needs access to the objects that it holds
It's not very clear what the question is, but I'll try.
When it comes to things that are application specific (like models,
controllers, etc), how should I manage the auto-injection of
dependencies?
Do you use a DIC? Did you write one, or do you use a library?
Maybe a library would help, I am the author of PHP-DI so I'm biased, but the library helps me auto-inject dependencies.
For example I can write:
class UserController
{
private $formFactory;
public function __construct(FormFactory $formFactory) {
$this->formFactory = $formFactory;
}
public function createForm($type, $data, $options) {
// $this->formFactory->...
}
}
In that situation, the DIC can detect what dependencies your controller want, and autoinject them. That makes life easier.
I happen to have a LARGE website, with maybe 30-40 different types of
models...do I really create a single application dependency manager to
handle each of these different types?
Why would you need that? I don't understand the need, maybe you need to explain a bit more what's the problem.
I have had people tell me that DIC's are not meant for domain stuff,
but more for framework stuff, and I have also heard the opposite.
Which is "right"?
IMO there's no difference between "domain stuff" and "framework stuff". The only thing that is hard though, is having a DIC injecting stuff in an entity, because that's not a "singleton" (not in the Singleton Pattern way): these objects are not "managed" by the DIC, you can create instances manually everywhere in your code. Example:
$user = new User();
If the User class needs a service, then everywhere in your code you have to do:
$user = new User($service);
On the contrary, you never need to create a service manually (you never need to call "new"), so you can let the container create the instance and inject everything.
I'm not very happy with my answer as it's a bit vague, but I have trouble identifying really what's your problem. Maybe you should give code examples, or at least explain a bit more.
PS: I have struggled to understand DI and what is a DIC too, don't settle for a "I think I get it a bit more now, though not totally", I did the same and it took me months to finally understand.
If it helps, read the introduction text at http://mnapoli.github.io/PHP-DI/ and maybe also: http://mnapoli.fr/controllers-as-services/ (not directly related, but it can help)
Why should I use Zend_Registry instead of the Singleton pattern?
My coworker and me recently had a discussion about this. His point was that we should use Zend_Registry for all consistent objects, but I wanted to use the singleton pattern, since Zend_Registry just does the same, but wrapped.
I have a problem with code like this:
$list = Zend_Registry::get('database')->getList($sql);
Since theres a chance that database isn't in Zend_Registry. In cases of lazy loading, I would have to make my own registry with information about specific objects in my system. Like if the database takes specific parameters on loadtime, then it would have to know this.
I would instead use getInstance and then all the code would reside in the same object. Does that make sense?
Even though you phrased your question as an either/or, might I suggest a third alternative?
I try to avoid both singletons and Zend_Registry wherever possible, since they function, in effect, as globals. When a segment of code can reach into the global ether - via a call to a singleton or a global registry - to get something it needs, it creates a hidden - or at least, a non-explicit - dependency that makes things harder to debug and unit-test.
In contrast, I try to follow dependency injection advice, paraphrased as: "Give a component what it needs. Don't make it find what it needs."
I find that for most entities for which I might feel I need a registry/singleton - db connections, loggers, etc - I can create them at Bootstrap, store them in the Bootstrap registry and inject them into my controllers, usually during init() using $this->getInvokeArg('bootstrap')->getResource('myResource'). Only controllers reach back into the Bootstrap. Then, any models or services that need these dependencies get them passed-in explicitly by the controller, either via constructor or by setter injection.
A hybrid approach to which I do sometimes fall back is to design my service/model classes with getters/setters for these dependencies - getDbAdapter() and setDbAdapter(); getLogger() and setLogger(), etc. The getter lazy-loads from the global registry - whether some singleton or by Zend_Registry, throwing exceptions when they are not where I expect them to be. In that sense, it is similar to what you are suggesting. It does violate the purist dependency injection philosophy. But at least the presence of the getter/setter methods explicitly demonstrates that there is a dependency and allows me to mock it out or to provide non-default implementations.
It does for simple blog or something. Otherwise you're stuck with only one DB instance. And that's NOT what you want in the long run. You may want to connect to other server (to log errors to central db, to import products from someone, ...) or connect as different user (for security reasons - you don't want your API to have access to admin_users table, but you still need to connect to it to check if user is valid in the first place).
You can do one-purpose registers (My_Db_Admin, My_Db_ReadOnly, ...) but that does not make much sense to me. Using registry you're not stuck with one instance. You can create one outside registry and work with it for a while and then trash it ;)
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.