Dependency Injection (And container?)

Discussion of testing theory and practice, including methodologies (such as TDD, BDD, DDD, Agile, XP) and software - anything to do with testing goes here. (Formerly "The Testing Side of Development")

Moderator: General Moderators

Post Reply
User avatar
The Phoenix
Forum Contributor
Posts: 294
Joined: Fri Oct 06, 2006 8:12 pm

Dependency Injection (And container?)

Post by The Phoenix »

Hello!

I am migrating a legacy code base to something more testable. To level set, we have about a dozen classes that are fairly close to being testable (I think?), but we have around 140 functions that have not yet been migrated to become classes.

One of the issues we have run into is that the majority of the code passes around the $db object, which is in the global scope (yuck!).

I've read with interest here that this sort of thing is best resolved with Dependency injection. I've started down that path, and have manual DI for most, with the $db object being a parameter for the calls.

Now I want to go the next step, and get those files testable. I understand that the way to do that should be to use the DI container. My project has composer, so I am leaning towards Pimple, which is a really simple DI container.

But before I start hacking on that, are my assumptions/understandings correct? Is using a DI container going to make it easier to test my units of code? With the DI container, can I also move other objects (like configuration values) into the container, so we just need to pass the container into the units of code, and get both DB & configs?

Any guidance is greatly appreciated.
User avatar
Christopher
Site Administrator
Posts: 13595
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Dependency Injection (And container?)

Post by Christopher »

I don't think a DI container will make you testing easier. A DI container helps by allowing you to predefine prerequisites to simplify creating object that inject or need dependencies injected. I think what you are looking for is Mocks. You can Mock your DB object and inject it giving you control without needing a database during testing.

PS - Congratulations on transitioning to classes and DI! And don't worry about common objects in the global scope (assuming register_globals is off as is normal).
(#10850)
User avatar
The Phoenix
Forum Contributor
Posts: 294
Joined: Fri Oct 06, 2006 8:12 pm

Re: Dependency Injection (And container?)

Post by The Phoenix »

Christopher wrote:I don't think a DI container will make you testing easier.
Hmm! Interesting. I was having trouble understanding how I was going to test relatively simple classes that relied on $db being there. After your post, I read up on Mocking a DB, and it seems it would work for most of the simple cases. But then I stumbled onto the dbUnit element, and *woah*, I can build an entire fake database for testing?! Awesome.
Christopher wrote:A DI container helps by allowing you to predefine prerequisites to simplify creating object that inject or need dependencies injected. I think what you are looking for is Mocks. You can Mock your DB object and inject it giving you control without needing a database during testing.
Well, to be honest, I didn't really know what I was looking for. I had some simple classes, and wanted to test them, but couldn't see past how to satisfy the $db need.
Christopher wrote:PS - Congratulations on transitioning to classes and DI! And don't worry about common objects in the global scope (assuming register_globals is off as is normal).
Well, see, that assumption is entirely reasonable. Unfortunately, its NOT the case in the code base I am working on! Ack! We have a horrible bit of code that takes the post/get super globals and sticks them in the global scope. Its a mess, and that needs to go. But in the meantime, I want to do the right thing where I can. For the new code, I'm trying to make it clean and testable, and where possible, to eliminate globals.

So one of my questions remains. Can I use a DI container to store both config variables and a database object? Or is that worse than just having a $config and $db object?

Just curious.

Thanks again!
User avatar
Christopher
Site Administrator
Posts: 13595
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Dependency Injection (And container?)

Post by Christopher »

The Phoenix wrote:We have a horrible bit of code that takes the post/get super globals and sticks them in the global scope. Its a mess, and that needs to go. But in the meantime, I want to do the right thing where I can. For the new code, I'm trying to make it clean and testable, and where possible, to eliminate globals.
I would recommend wrapping the HTTP vars in a Request object that is a container for those value, plus support for dealing with post, get, ajax requests.
The Phoenix wrote:So one of my questions remains. Can I use a DI container to store both config variables and a database object? Or is that worse than just having a $config and $db object?
Typically you would use some kind of Container object to hold the config variables. And a Registry to hold the $config and $db (and other) objects. It up to you whether you put the $config object and the $db object in a Registry and inject that, or inject the DI object and use it to instantiate objects where needed. Or a mix. DI objects are often used to instantiate objects that have complex wiring -- unlike the $config and $db objects to which you usually just pass an array or a few params.
(#10850)
Post Reply