Somewhat new to OOP - class interaction...?

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

User avatar
TheMoose
Forum Contributor
Posts: 351
Joined: Tue May 23, 2006 10:42 am

Post by TheMoose »

I think it's more a matter of modularity for your project. If you globalize your variable for that class, you're restricting that class to only one instance of a connection. And thus every object of your class that you instantiate, you are limiting it to that one specific connection, whereas if you merely use a reference, you can have multiple connections to different databases depending on the object's reference.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Everah wrote:OK, so I have a question about this. I was told on these forums (somewhere) that globalizing an object/var for use in a class was not the right thing to do. What I have done is something along this lines of...

Code: Select all

<?php
class MyClass
{
    function MyClass()
    {
        global $db; // This is my DBAL object
        /* Do something here using the $db object */
    }
}
?>
So should I be using a reference to the $db object instead of using a global? I have wondered about this for a bit and I think this is a good place to pose the question (seeing as Ninja's is somewhat similar).
The problems with globals is twofold: side effects and testablity. First is side effects. Say for example you intentionally or unintentionally do:

Code: Select all

<?php
class MyClass
{
    function MyClass()
    {
        global $db; // This is my DBAL object
        /* Do something here using the $db object */

        $db = "This is the title to my page";

        // or intentional 
        $db = new PostgresConnection();
    }
}
?>
Your program now stops working somewhere else, but this works fine, and you have to track down everywhere that accessed the global. This is one of the essential ingredients in spaghetti sauce.

Second is testablity, and it relates to side effects, how you test the module on its own? When it is instansiated it may or may not be usable based on an external factor. If you composite the $db connection then you have explicitly documented the documentation -- with code. And that is the best way to document.
(#10850)
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post by RobertGonzalez »

arborint wrote:The problems with globals is twofold: side effects and testablity... First is side effects...
Second is testablity, and it relates to side effects, how you test the module on its own? When it is instansiated it may or may not be usable based on an external factor. If you composite the $db connection then you have explicitly documented the documentation -- with code. And that is the best way to document.
OK, that makes a lot of sense to me. So to incorporate what has been said in this thread (and I think what Ninja was getting, not totally sure) is that using a class (that has already been instantiated) within another class can be done by passing the object by reference to the class constructor, a la...

Code: Select all

<?php
class MyClass
{
    var $db; // object reference to DBAL for this class
    function MyClass(&$db)
    {
        $this->db = $db; // Now I am using my DBAL object, instead of globalizing it or copying it
        /* Do something here using the $db object */
    }
}
?>
Is this an appropriate way to do it? Is this what Ninja was asking? Did I totally hijack his thread? I am sorry if I did, it's just that this question has been eating at me since it was posed to me.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

all very helpful... even you everah... thanks everybody
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

Is this an appropriate way to do it? Is this what Ninja was asking? Did I totally hijack his thread? I am sorry if I did, it's just that this question has been eating at me since it was posed to me.
Yep, that's fine. The other methods are to use a Singleton or Registry (or in my case a ServiceLocator). Other ways too, but I have seen few examples in PHP...

Back on another q earlier. $obj::doThis() is a static function call (you don't need to instantiate the onject in order to use the method - just include the class). Easiest way of thinking about it - it's almost identical to a bog standard procedural function. I used it in an earlier example, because ServiceLocator::getInstance() is a static method which creates/stores/returns an instance of ServiceLocator (in essence it instantiates the class containing it). Reading up on the Singleton pattern more fully would explain this better...
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post by RobertGonzalez »

Thanks Maugrim (and everyone else). For some reason this all makes so much more sense to me. I feel so much smarter. WOW, I need a drink.

And thanks to Ninja for not ninjitsu'ing my sorry behind after I hijacked his thread.
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

I don't mind sharing my thread... just don't try and take my 'thanks' thread in general discussion or I will come after ya
User avatar
RobertGonzalez
Site Administrator
Posts: 14293
Joined: Tue Sep 09, 2003 6:04 pm
Location: Fremont, CA, USA

Post by RobertGonzalez »

It'll be tough, but I think I can keep my hands sort of off that thread mostly. :wink:
Flamie
Forum Contributor
Posts: 166
Joined: Mon Mar 01, 2004 3:19 pm

Post by Flamie »

Well, personally when I create a class, I think of it as defining a new "variable" type, which is pretty much what you are doing, and then you want to think what that kind of variable should be doing. Those will be your methods (or functions). Once you figure out what functions you will need, you figure out what data those functions need, and make them your data members.
So to do an exemple, lets say you want to make a blackjack class:
-You need to be able to deal a card
-You need to be able to calculate the points in your hand
-You need to be able to run the dealer's AI.
etc etc

So those things will be your class functions, and what do you need to make those functions work?
-a hand to hold the cards (array)
-a deck of cards (another array)
etc etc

So depending on how sofisticated you want your class to be you can have mroe functions etc, but you gotta always keep in mind that sometimes overcomplicating your class isnt too good, so really try to make your class with what you really need to be in it.
Afterall, the most important reason people use OOP is for "reusable" code, having a class where 90% of your functions are uneeded doestn make that class very reusable now does it :)
User avatar
Luke
The Ninja Space Mod
Posts: 6424
Joined: Fri Aug 05, 2005 1:53 pm
Location: Paradise, CA

Post by Luke »

I'd have to say the best step I've ever taken to improve my php scripts is planning ahead.
Flamie
Forum Contributor
Posts: 166
Joined: Mon Mar 01, 2004 3:19 pm

Post by Flamie »

I totally agree with you, writing a as detailed as possibled technical design document before hand is the best thing you could do. The hardest thing to do is sticking to it tho :oops: :oops:
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

Unit testing and refactoring... Planning will get you something that works, not necessarily something that's easy to maintain (or debug for that matter).
So to do an exemple, lets say you want to make a blackjack class:
-You need to be able to deal a card
-You need to be able to calculate the points in your hand
-You need to be able to run the dealer's AI.
etc etc

So those things will be your class functions, and what do you need to make those functions work?
-a hand to hold the cards (array)
-a deck of cards (another array)
etc etc
I would never have a blackjack class. Your three requirements to play, I would provisionally add as three interacting classes. Maybe I could reuse the CardDeck class in designing a Poker game, or the create a set of Dealer sub-classes for differing games, and the same for points. Lumping everything into one class defeats the purpose of OOP. Why not just make it procedural to start with if putting everything in one class?

A class should have a single focused purpose and responsibility. Either it deals, calculates points, or controls the game logic - doing all three means adding a new game would have me either a) refactoring at some later stage, or b) duplicating common code and thus duplicating maintenance for bugs in these areas.
User avatar
JayBird
Admin
Posts: 4524
Joined: Wed Aug 13, 2003 7:02 am
Location: York, UK
Contact:

Post by JayBird »

Just to continue this, what are the pro's and con's with this method?

Code: Select all

class DBConnect
{
    function DBConnect()
    {
        // connect to database and a whole host of other functions
    }
} 

class MyClass
{
    var $db;
    function MyClass()
    {
        $this->db = new DBConnect();
    }
}
Flamie
Forum Contributor
Posts: 166
Joined: Mon Mar 01, 2004 3:19 pm

Post by Flamie »

it'd be hard to say the pro's and cons, it depends what your "whole host of other functions" are.
My connect class is pretty simple:

Code: Select all

<?php
class connect
{
	function connect()
	{
		$this->db = mysql_connect('localhost','usermame','password') OR die("Unable to connect");
		mysql_select_db('database_name');
	}
	function get_id()
	{
		return $this->db;
	}
	function close()
	{
		mysql_close($this->db);
	}
}
?>
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Pimptastic wrote:Just to continue this, what are the pro's and con's with this method?
I think the pro is simplicity, the cons are lack of reusability and flexiblity. And as ever it is about dependencies. Both of your connection classes really has not dependencies -- the price you pay is that there is no reuse -- they are only good for that database/user/password because is hard coded into the class. Not that much of a problem, but you have decentralized configuration which has a maintenance consequence.

MyClass has similar issues. It not only needs to know the interface for DBConnect, but it also needs to know how to instansiate it -- sort of a double dependency. That is a tradeoff for simplicity. The more dependencies something has the greater chance down the road it will be inflexible, harder to change, and be more sensitive to side effects.

However it may be that MyClass goes happily along, stays simple, and does not need the flexiblity.
(#10850)
Post Reply