Passing DB object around
Moderator: General Moderators
Passing DB object around
Which do you recommend - using singleton to create/return the db object, or just passing it to all classes? The first approach would make my life a bit easier but that's global stuff. The second approach, as I understand, is the preferable one, but it forces me to also pass the db object to the classes which extend other classes, which I do not like that much. Which way is a better one in your opinion? Which is considered better when used together with unit testing?
Marcus Baker wrote a really good article on this a while back in the php|architect magazine. He elaborated many different options (his article was generic to any dependant object, but certainly applies to a database object).
Among the options are:
1) always create new by hand
2) always create from a factory
3) use a global variable
4) use a singleton (stealth global)
5) use a registry (reference hiding in a stealth global)
6) pass it in to the constructor
7) have a setter method to set it after creation
8 ) use 6 or 7 in combination with a Dependancy Injection framework
I am sure I have forgotten several of the originally listed options, but I think you get the picture.
One technique I have used on a reasonable number of small scripts it to combine 2 and 7. This allows me to default the database connection in most instances, but allows for overriding that default when I want to (for instance, during unit testing).
HTH
Among the options are:
1) always create new by hand
2) always create from a factory
3) use a global variable
4) use a singleton (stealth global)
5) use a registry (reference hiding in a stealth global)
6) pass it in to the constructor
7) have a setter method to set it after creation
8 ) use 6 or 7 in combination with a Dependancy Injection framework
I am sure I have forgotten several of the originally listed options, but I think you get the picture.
One technique I have used on a reasonable number of small scripts it to combine 2 and 7. This allows me to default the database connection in most instances, but allows for overriding that default when I want to (for instance, during unit testing).
HTH
- Maugrim_The_Reaper
- DevNet Master
- Posts: 2704
- Joined: Tue Nov 02, 2004 5:43 am
- Location: Ireland
It depends (for me at least). If the DB object is getting used in background (say a Data Access layer) I'll try to pass it as a parameter to the constructor. If its being used for some reason upfront (a lot) I'll consider a singleton, esp. if it starts looking like the parameter method is being thoroughly overused which is annoying because I hate clogging up the parameter list.
Passing to a constructor (sweatje's method) is usually fairly good for most cases. A lot depends on how your client code (what actually does actions) handles object creation - is it there and then, or handled by an include?
Passing to a constructor (sweatje's method) is usually fairly good for most cases. A lot depends on how your client code (what actually does actions) handles object creation - is it there and then, or handled by an include?
Passing the db construct in and using a singleton both imply that the mechanism in need of this constructs services know it's interface. If that's the case, why not make the construct aware of a factory and be done with it. If your objects are working together this closely, why not let them also take care of certain thing you may otherwise hack out by hand?
How do you then substitute in a mock object for testing if you have hard coded the construction dependancy?BDKR wrote:Passing the db construct in and using a singleton both imply that the mechanism in need of this constructs services know it's interface. If that's the case, why not make the construct aware of a factory and be done with it. If your objects are working together this closely, why not let them also take care of certain thing you may otherwise hack out by hand?
- Maugrim_The_Reaper
- DevNet Master
- Posts: 2704
- Joined: Tue Nov 02, 2004 5:43 am
- Location: Ireland
Loose wiring? 
Code: Select all
function constructor(&$db) {
if(!is_object($db))
{
$this->db =& AppHelper::getDB(); // in app
}
else
{
$this->db = $db; // for unit testing
}
}Essentially what I recomended in my first post as " combine 2 and 7" except yours is "combine 2 and optional 6". The only issue there is PHP4 optional objects by reference are tricky.Maugrim_The_Reaper wrote:Loose wiring?![]()
See http://blog.casey-sweat.us/?p=14
- Maugrim_The_Reaper
- DevNet Master
- Posts: 2704
- Joined: Tue Nov 02, 2004 5:43 am
- Location: Ireland
The bull**** answer:sweatje wrote: How do you then substitute in a mock object for testing if you have hard coded the construction dependancy?
; ksudif9q[3[4j1cl ;nc[90zayu fr9[c4rlasd98uq389-4yu pcbi cvh 8aeh 45 a;9r8vu9-3q4un ;kbuiuvu8pd7 yhr9af
The real answer:
Not being someone big on this form of testing, I'd have to say that's a good question to wich I don't have an answer. LOL!
However, I'm all ears.
Let me also add something else. Part of my original point is, however unspoken, that if the various objects being used are aware
of the db object interface, then they are part of a loose framework of sorts. My contention is that if it's gotten that far, let those
individual objects pass their own messages back the factory when they need handles to objects.
Of course, the more I think about it, I can see how it can make testing using mock objects difficult.
Phppatterns is back online: Marcus Baker's article on the Registry makes an interesting read - and includes some discussion on how to write a test-able Registry.
LOL! It's funny because I realized after reading his article that my factory class is also acting as a registry class.McGruff wrote:Phppatterns is back online: Marcus Baker's article on the Registry makes an interesting read - and includes some discussion on how to write a test-able Registry.