Page 1 of 1

Passing DB object around

Posted: Tue Oct 18, 2005 3:29 am
by Ree
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?

Posted: Tue Oct 18, 2005 5:49 am
by feyd
It sounds like you've already made your decision, so run with it.

Posted: Tue Oct 18, 2005 6:10 am
by Ree
Well, I haven't yet, that's why I'm asking for recommendations.

Posted: Tue Oct 18, 2005 7:00 am
by sweatje
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 :evil:
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

Posted: Tue Oct 18, 2005 7:37 am
by Maugrim_The_Reaper
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?

Posted: Fri Oct 21, 2005 7:47 am
by BDKR
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?

Posted: Fri Oct 21, 2005 8:30 am
by sweatje
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?
How do you then substitute in a mock object for testing if you have hard coded the construction dependancy?

Posted: Fri Oct 21, 2005 8:48 am
by Maugrim_The_Reaper
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
    }
}

Posted: Fri Oct 21, 2005 10:25 am
by sweatje
Maugrim_The_Reaper wrote:Loose wiring? :)
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.

See http://blog.casey-sweat.us/?p=14

Posted: Fri Oct 21, 2005 11:05 am
by Maugrim_The_Reaper
You're right - I keep forgetting those niggling issues with < &var='' >.... :roll: Stupid of me.

Posted: Fri Oct 21, 2005 2:31 pm
by BDKR
sweatje wrote: How do you then substitute in a mock object for testing if you have hard coded the construction dependancy?
The bull**** answer:
; 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.

Posted: Fri Oct 21, 2005 6:34 pm
by McGruff
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.

Posted: Mon Oct 24, 2005 12:42 pm
by BDKR
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.
LOL! It's funny because I realized after reading his article that my factory class is also acting as a registry class.

Posted: Mon Oct 24, 2005 12:55 pm
by sweatje
In my book I talk about that very concept. Registry is a wonderful pattern to embed inside a parameterized Factory.

Posted: Fri Oct 28, 2005 8:52 am
by BDKR
I'm going to have to make a point of reading your book. :D