When you start needing to inject that many objects, you need to ask whether the object that receives them is responsible for too much. Can it be broken down into smaller pieces?
In this example there would be like 7 objects to inject into the other classes, that seems like a lot. Am I going about this wrong? When you start needing to inject that many objects, you need to ask whether the object that receives them is responsible for too much.
Can it be broken down into smaller pieces? If it really can't, then consider encapsulating related objects in another class. Perhaps your session, logger, and config objects can be injected into an App or Application object?
Edit: I notice most of the other answers so far talk about Singletons. Note that Singletons are the enemy of DI. Great Google tech talk on this here.
Edit 2: What I mean by encapsulating is, instead of injecting Session, Logger, Config, etc. All into your Account class, maybe they should be injected into an Application class, and an Application instance can be injected into Account.To be honest, this is still a piece of DI I'm wrapping me head around, but what I'm starting to see is this: You should only inject into Account the objects it will directly need to manipulate. Those objects may need to manipulate yet other objects, but Account doesn't need to know about it. Often, you'll find you don't even need as many "layers" as you thought, though.
If you find you're injecting stuff all over the place, consider various ways of re-structuring your application. Let me pull a piece of code from the Pylons documentation on the model: a = model.Person() a. Name = "Aaa" a.
Email = "aaa@example. Com" meta.Session. Add(a) (Don't worry about meta.Session... basically it handles interaction with the database.) Here, we instantiate a Person, set a couple of its attributes, and then save it.
You'll notice the Person class knows nothing about the database, and in fact doesn't even have a save() method. Instead, we pass it to the database class (meta. Session) which saves it.
We've separated concern for Person logic from the database code. Meta. Session could work a dozen different ways, but as long as it knows how to read Person, we're fine.
(in this case, during application initialization, it read the definition of all the application's models). Okay, I'm going to sum up, because I've obviously rambled a lot here. There is no one "correct" answer to your question (as far as I know, but I don't proclaim to be a DI expert by any means).
Yes, injecting several objects is probably indication of some need to restructure, but you have a number of considerations to make: Is the object receiving the injection responsible for too much; can it be separated out? Are you only injecting objects that the recipient class will directly need to utilize? Are you injecting the wrong direction; can your Account object be injected into your Database instead of the other way around?
I added a little to my OP, but what do you mean by "encapsulating related objects in another class" – jasondavis Jan 18 at 21:24 my comment is getting long, so I'm going to edit it into my original answer... – keithjgrant Jan 18 at 21:31 1 +1 The advantage of dependency injection is so that things like the Logger, which the Account class shouldn't know how to create, can be provided from elsewhere. If many of these things can be instantiated during some configurable and environment-aware initialization of your Application class, then injecting the Application gives you a nice tidy package. And you won't have to change every constructor in your project when you add a new, widely used class.
– grossvogel Jan 18 at 21:48 1 I'm not a fan of singletons myself, if we are talking about the GOF singlton. However having a single instance of certain objects is not an anti-pattern per se; in fact, many DI containers allow registering instances as (non-GOF) singletons. I would also argue that Session, Logger, and Config are cross-cutting concerns, and may not be the best candidates for DI.(All that aside, +1 for your answer :).
– Phil Sandler Jan 18 at 21:52 1 More food for thought: blog.ploeh. Dk/2010/02/02/RefactoringToAggregateServices. Aspx – keithjgrant 10/02/028 at 0:35.
You can do this via static class/singleton with methods like getCore, getDatabase, getConfig... These methods can return either instance or type name, which can be later instantiated as $var = new $typename($arg1,$arg2,...) Or each of the consumer classes can have static methods like setDatabase, setCore..., so you configure your dependencies once and don't have to bother about them any more. But I think the first solution is better. Neither of these solutions is entirely optimal, but both are better than typing eight parameters every time you want to create a new instance of eg.Photo.
1 that sounds to defeat the purpose if he's doing dependency injection though. – nos Jan 18 at 20:45 You use an intermediary class to centralize the dependencies, but in principle it remains the same. It can enforce a presence of interface.So then the ability to change the actual implementations of core/database... etc. Can change without changing individual classes, as long as the interface is preserved.
– MatÄ›j Zábský Jan 18 at 20:48 @nos, he also mention a registry system which is not Dependency Injection – RobertPitt Jan 18 at 20:55.
I've always preferred the Registry approach. Reasons: Larger Scope Simple to get constructors are freed from having objects as variables (allows better usage) Allows you use more objects in your classes as your free to grab what you need, when you want. Although there is another method you can try and thats using the singleton pattern, where you would have a method in every class that keeps track of its own object.
Fors example, create an interface like so: interface ISingleton { public static getInstnace(); } Then for every object you can add the method that is used for the getting of the instance. Class SomeObject implements ISingleton, ISomeThingElse { private static $_instance; public static getInstance() { if(self::$_instance === null) { self::$_instance = new SomeObject(); } return self::$_instance; } } This way your always keeping your same instance of the object as well as having a global scope. Example: public function GetUser($id) { return Database::getInstance()->fetchUserById($id); } Hope this helps.
There is another way you can do and that's creating a context class, let me try and explain: The class would act like a registry but disposable, for example: class Context { private $objects = array(); public function Add($key,$Object) { $this->objects$key = $object; } public function __get($key) { return isset($this->objects$key)? $this->objects$key : null; } } And use that as a container to hold your objects like so: $Context = new Context(); $Context->Add("database",$database); $Context->Add("logger",$logger); $Context->Add("session",$session); $UserObject = new RegularUser($Context); This way you can group a set of objects and pass the same context into several other library objects.
4 -1 This is the antithesis of dependency injection, and is a horrible design decision. – cdhowie Jan 18 at 20:58 Please post an answer explaining your proposal. – RobertPitt Jan 18 at 21:01 I have used code like this in the past but I am hoping to improve my code so I am looking for other alternatives – jasondavis Jan 18 at 21:26 Thats perfectly fine, I thought I would throw a technique in the mix for you.
– RobertPitt Jan 18 at 21:31 Also, I would love to see @cdhowie's implementation as he sounds like he has a better view on the matter :) .. Knowledge is power! – RobertPitt Jan 18 at 21:32.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.