Page 2 of 3

Re: Using classes within other classes

Posted: Thu Dec 11, 2008 11:43 am
by Eran
The logical scope for a database object is a database class?!? I can think of no reason to get an instance statically from the class except for a Singleton. Unless you are saying that $db = DB::getInstance(); is always better than $db = new DB();
I wasn't going to respond any further as we are very much apart on this, but you seemed so bewildered by my statement...
I was talking about storing a database connection object inside a database adapter class. The database connection may be an actual database connection resource or a database connection class, it's not an instance of the database adapter class. The point was that the database adapter class is responsible for retrieving the database connection.

For me it's a logical scope to put it in, and that's the primary motivation for me to use that approach. If you don't find it logical then I can't fault you for using a different approach. To each his own.

Re: Using classes within other classes

Posted: Thu Dec 11, 2008 11:48 am
by VirtuosiMedia
Just a quick note to everyone: This wasn't just a drive-by question, I'm just doing a lot more reading and absorbing than discussing at this point. I appreciate the discussion, though.

Re: Using classes within other classes

Posted: Thu Dec 11, 2008 4:25 pm
by Christopher
pytrin wrote:I wasn't going to respond any further as we are very much apart on this, but you seemed so bewildered by my statement...
I was talking about storing a database connection object inside a database adapter class. The database connection may be an actual database connection resource or a database connection class, it's not an instance of the database adapter class. The point was that the database adapter class is responsible for retrieving the database connection.

For me it's a logical scope to put it in, and that's the primary motivation for me to use that approach. If you don't find it logical then I can't fault you for using a different approach. To each his own.
I think my bewilderment is that I don't understand how this relates to getting objects via parameter vs from a static vs from a Registry? The reason a database connection is inside a database adapter class is because it needs it to do it's job. You say it's logical to put it there, I say necessary. But the point of a Registry or Singleton is to make objects available -- not to use them internally. Sprinkle in "scope naming is important to me" and "lack of semantics is what bothers me" and I remain as usual ... bewildered. ;)

Re: Using classes within other classes

Posted: Thu Dec 11, 2008 4:38 pm
by Eran
I didn't say anything about the database class being a singleton - I said that a registry is better off as a singleton. I prefer to avoid registries regardless.

In the case of the database adapter object, you can make sure each instance reuses the same connection by making the connection a static protected member of the database adapter class. Only the database adapter object can retrieve it (and pass it around if necessary) and so it is responsible for it - I consider this design semantics. A database class is responsible for the database connection, a cache class is responsible for storing a "global" cache path as a static protected member and so forth.

This is as opposed to a registry which I consider generic since it has no particular relation to any object it hold and so it's basically a nameless generic scope. It holds everything that needs to be accessed from several directions - but it can't be responsible for everything it holds, and I believe that is outside of its scope. You implement methods like getDb() which I feel belong to a database class, and those distinctions matter to me.

Not saying there is an absolute truth, just explaining my train of thought.

Re: Using classes within other classes

Posted: Thu Dec 11, 2008 7:27 pm
by Christopher
Yeah, I understood what you were saying. I just don't see the parallel. The database is not responsible for providing the connection ID. The cache is not responsible for providing the path. Those are just things internal to them. Sure they are responsible in the same way that every class is responsible to every non-public property. But the the Registry a completely different thing. It is responsible for providing objects -- not being responsible for those objects' internals. What is apparently apples and apples to you, is apparently apples and oranges to me. Hence my bewilderment because it seems very important to you, yet unrelated to me.

Re: Using classes within other classes

Posted: Thu Dec 11, 2008 7:48 pm
by Eran
It is responsible for providing objects -- not being responsible for those objects' internals
Correct. It can not be responsible for those objects internals, and that's why I don't want to use it to create / retrieve those objects. I prefer a database adapter class, which can be responsible for properly configuring a database connection to create and and cache such a connection as a static property. The same with a Cache class and maintaining it's own configuration data (such as the temporary cache path).

I can see I have a hard time explaining why it is important to me. This reminds me of a lot of discussions I had with programmers about things like object-orientation and coding standards - things that are hard to understand until you use them for a while and feel for yourself how they can help you. I don't think there's a way for me to convince you that I might have a point. From my experience I found that as a project increases in size, it helps that I separated the retrieval / instancing methods to logical scopes instead of condensing them all in a generic DI object.
Hence my bewilderment because it seems very important to you, yet unrelated to me.
Don't be bewildered ;) it shouldn't be surprising at all that two different developers approach the same issue with different mindsets.

Re: Using classes within other classes

Posted: Fri Dec 12, 2008 10:41 am
by josh
You can still "cache" values in regular instance variables, without them being static. Static variables mean the "class" has the variable, instead of the "object". Its more like comparing oranges to apples instead of oranges to fruit. Fruit is the type, but you might need fruit to be an object of type "organic material". Objects allow for this flexibility, classes are a way of _hard coding_ types. Object composition allows them to vary.

What if you had to make an adapter for your adapter? You'd have to update the singleton calls to your 1st adapter to use one of the "sub" adapters. With object composition each 1st adapter object holds a sub-adapter as an instance variable. The code that uses the 1st adapter doesn't know about sub-adapters. The reason you are experiencing confusion is because you have not had to change code and felt the pain of having the stuff hard wired, therefore you don't see the benefit.

pytrin wrote: it helps that I separated the retrieval / instancing methods to logical scopes instead of condensing them all in a generic DI object.
"it helps that I separated the dependencies to their own logical scopes [objects] instead of condensing them all in a generic global state."

The objects are the scopes.

Re: Using classes within other classes

Posted: Fri Dec 12, 2008 2:23 pm
by Christopher
pytrin wrote:Correct. It can not be responsible for those objects internals, and that's why I don't want to use it to create / retrieve those objects. I prefer a database adapter class, which can be responsible for properly configuring a database connection to create and and cache such a connection as a static property. The same with a Cache class and maintaining it's own configuration data (such as the temporary cache path).
I guess I am wondering why DB and Cache are different that the many other objects in the system. They certainly would fall under "common objects" that are candidates for using a Registry.
pytrin wrote:I can see I have a hard time explaining why it is important to me. This reminds me of a lot of discussions I had with programmers about things like object-orientation and coding standards - things that are hard to understand until you use them for a while and feel for yourself how they can help you. I don't think there's a way for me to convince you that I might have a point. From my experience I found that as a project increases in size, it helps that I separated the retrieval / instancing methods to logical scopes instead of condensing them all in a generic DI object.
I have actually gone the opposite direction. In the past I have used the actual class to get objects -- using a Factory for the DB for example. However I have been stung by it many times. I often use an existing codebase for an new client, but customize it. The "logical scope" think caused a lot of rework for me. Using a Registry makes it become "logical" in my way of thinking, because I am asking for "the DB for this project" and I don't care about what the actual class it. So my app only cares about getting "a cache object" or "a db object" and does not care which variant of that object it is.
pytrin wrote:Don't be bewildered ;) it shouldn't be surprising at all that two different developers approach the same issue with different mindsets.
I am actually pretty selfish -- I usually debate to crowbar ideas out of smart guys like you! ;) I think I have a little broader understanding of some of these issues and will experiment with some of your ideas in upcoming projects.

Re: Using classes within other classes

Posted: Fri Dec 12, 2008 3:00 pm
by Eran
You can still "cache" values in regular instance variables, without them being static.
Of course you can, but then you can't ensure every new instance uses the same resources (a database connection for example). Unless you use something like a registry to transport those resources.
What if you had to make an adapter for your adapter? You'd have to update the singleton calls to your 1st adapter to use one of the "sub" adapters. With object composition each 1st adapter object holds a sub-adapter as an instance variable. The code that uses the 1st adapter doesn't know about sub-adapters. The reason you are experiencing confusion is because you have not had to change code and felt the pain of having the stuff hard wired, therefore you don't see the benefit.
This is a good point, however that adapter will basically instance the old adapter class, which contains the static connection, and so it's a non-issue. Pay attention that I said the adapter class is not a singleton, but the database connection is.
"it helps that I separated the dependencies to their own logical scopes [objects] instead of condensing them all in a generic global state."

The objects are the scopes.
Actually, I meant it as I wrote it. Static properties / methods belong to the class, not the object and so that is the scope I am referring to.
I guess I am wondering why DB and Cache are different that the many other objects in the system. They certainly would fall under "common objects" that are candidates for using a Registry.
They are different because the encapsulate separate concerns. The fact that they need to be accessed globally in the application doesn't make them "common" objects - just the opposite! they're very unique.
I have actually gone the opposite direction ... However I have been stung by it many times ... Using a Registry makes it become "logical" in my way of thinking
Well I can't argue with this of course. We each draw from our own personal experiences and form our own biases.

Re: Using classes within other classes

Posted: Fri Dec 12, 2008 3:11 pm
by josh
pytrin wrote:Actually, I meant it as I wrote it.
I was showing how your logic could be used to argue contrary to your argument.
pytrin wrote:
You can still "cache" values in regular instance variables, without them being static.
Of course you can, but then you can't ensure every new instance uses the same resources (a database connection for example). Unless you use something like a registry to transport those resources.
$a = new SharedResource(); // $a is a REFERENCE, PHP is your "registry".

new b( $a ); // b holds a reference to a
new c( $a ); // c holds a reference to a

// if $a changes both $b and $c point to the "new" object.

Re: Using classes within other classes

Posted: Fri Dec 12, 2008 3:16 pm
by Eran
I'm afraid I'm not following ...

Re: Using classes within other classes

Posted: Fri Dec 12, 2008 3:19 pm
by josh
pytrin wrote:I'm afraid I'm not following ...
PHP's objects are your "logical" scopes. Most objects can be found by navigating object relationships, not every object needs to hold a reference to every other object in the system.
*edit*

Actually I meant to link you this video = http://www.youtube.com/watch?v=-FRm3VPhseI

Watch that ^^^^ and be enlightened. You may not be doing TDD but the arguments still ring true.

Re: Using classes within other classes

Posted: Fri Dec 12, 2008 4:06 pm
by Eran
not every object needs to hold a reference to every other object in the system.
I don't know how you came to the conclusion that what's I'm doing from what I've written...

Re: Using classes within other classes

Posted: Fri Dec 12, 2008 4:40 pm
by allspiritseve
pytrin wrote:
not every object needs to hold a reference to every other object in the system.
I don't know how you came to the conclusion that what's I'm doing from what I've written...
Without a registry you need to know exactly what object you're calling. With one, you could call for a type and not care whether it's Object_TypeA or Object_TypeB. Because there's that indirection, you can let the reigstry (or whoever sets up the registry) select the appropriate object. I believe that's where he was going with that.

Re: Using classes within other classes

Posted: Fri Dec 12, 2008 9:12 pm
by josh
Look, i'm arguing singletons.. not registries.. granted 99% of people probably associate registries with singletons. The most common argument for singletons is "without a singleton, every object needs to have a reference to the commonly used objects".. simple un-true. With dependency injection the code expresses it's meaning, and will not execute without dependencies supplied. With a registry object you have to write code inside your class that make sure the dependencies are present in the registry. None of this has anything to do whether or not to use singletons though