Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this too many dependencies to inject into an object through the constructor?

I am working on a social network type project in OO PHP and I do not want to use an existing framework. The main point of doing this project is to help me learn about more stuff.

This question is more about dependency injection.

Let's say I have these classes:

core class - some core methods to do stuff in the app
config class - loads site config stuff
database class - connects to mysql and does all database related stuff
logger class - used to log errors and debug info
captcha class - for captcha on forms
session class - initiates a session start and adds, removes, gets session variables to use in the app
cache class - similar to session class but for caches items (files cache, memcache, apc cache. I may even add my session stuff to this class someday since all these cache's can use the same type of methods)

All the classes above will most likely be used on every page load in my app (I probably missed some more classes that will be added later on)

Now in addition to the above classes which will need to be injected into most other classes, I will have many many more classes. I will have a secion called modules which will have stuff like...

account class - creates new users, authenticates users, logs users in and out of the app, update user settings, and much more.
users class - shows users profiles, shows users online, new users, all stuff to show users of the site
forums class - will be for the forums section
blogs class - for the blogs section
photos class - all photo related stuff
comments class - handles comments for photos and profiles

There will be many more of these type of classes for different sections of the site.
This second set of classes listed above for sections will most likely require most of the classes from the first set to be injected into them.

So should I use a registry to store the objects from the first set of classes and just inject the registry into all the class objects in the second set of classes?

Or should I use the constructor to load them? 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?

---EDIT---
I am aware of the singleton pattern but I don't think it is my best option here

---EDIT 2---
As some have mention, needing to pass in as much as 7 objects does seem like a LOT and that is why I am looking for suggestions. Luckily for me this project is at the beginning stages so now is the time for changes to the structure.

An example would be a class in my forums section. The forums class would need access to session data, possible cached data, the configs object, database object. AM I going about this the wrong way?

like image 701
JasonDavis Avatar asked Jan 18 '11 20:01

JasonDavis


1 Answers

Or should I use the constructor to load them? 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 = "[email protected]"
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?
like image 194
keithjgrant Avatar answered Oct 13 '22 00:10

keithjgrant