Somewhat new to OOP - class interaction...?
Moderator: General Moderators
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.
- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
The problems with globals is twofold: side effects and testablity. First is side effects. Say for example you intentionally or unintentionally do: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...
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).Code: Select all
<?php class MyClass { function MyClass() { global $db; // This is my DBAL object /* Do something here using the $db object */ } } ?>
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();
}
}
?>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)
- RobertGonzalez
- Site Administrator
- Posts: 14293
- Joined: Tue Sep 09, 2003 6:04 pm
- Location: Fremont, CA, USA
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...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.
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 */
}
}
?>- Maugrim_The_Reaper
- DevNet Master
- Posts: 2704
- Joined: Tue Nov 02, 2004 5:43 am
- Location: Ireland
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...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.
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...
- RobertGonzalez
- Site Administrator
- Posts: 14293
- Joined: Tue Sep 09, 2003 6:04 pm
- Location: Fremont, CA, USA
- RobertGonzalez
- Site Administrator
- Posts: 14293
- Joined: Tue Sep 09, 2003 6:04 pm
- Location: Fremont, CA, USA
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
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
- Maugrim_The_Reaper
- DevNet Master
- Posts: 2704
- Joined: Tue Nov 02, 2004 5:43 am
- Location: Ireland
Unit testing and refactoring... Planning will get you something that works, not necessarily something that's easy to maintain (or debug for that matter).
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.
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?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
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.
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();
}
}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:
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);
}
}
?>- Christopher
- Site Administrator
- Posts: 13596
- Joined: Wed Aug 25, 2004 7:54 pm
- Location: New York, NY, US
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.Pimptastic wrote:Just to continue this, what are the pro's and con's with this method?
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)