Archive for the Category » OOP «

Sunday, February 28th, 2010 | Author: Dave

not to implementations…

It was one of those days where those six words made a little more sense. I’m working on a game project that uses a Wii remote for control. I got sick of always having to start the bluetooth, then start the Wii Flash server and then turn on the IR bar, all so I could check some code change. See, I turn off the sensor bar and wii mote when I’m working in order to save batteries, and it’s a bit aggravating turning it back on so often. I decided I should be able to use the mouse if I wanted, and not have to always rely on the wii remote when testing.

I had something like:

public class Engine extends Sprite
{	
	private var controller:WiiController;
 
        public function Engine()
	{			
		controller = new WiiController();
        }
        private function gameLoop(e:Event):void
	{				
		controllerIcon.setPosition(controller.getPosition());			
	}

I have a controller variable, which is an instance of the WiiController class. I can get the current position by calling the getPosition method. Similarly, if I want to pass the controller instance to a new class I would use something like: intro.waitForInput(controller) and then in the intro class I’d do: public function waitForInput(con:WiiController). Great.
But what happens when I want to use an instance of MouseController instead of WiiController? If there’s a getPosition method in MouseController, I can keep the same call in gameLoop. But anywhere the variable is typed, like when being passed to intro, WiiController will need to be changed to MouseController. Making all these changes is both cumbersome and prone to error.
This is where interfaces come in handy. An interface is like a contract in that if a class implements it, then the class must contain those methods outlined by it. Any public access for the class, must be outlined by the interface. The interface itself contains only method signatures, it is up to the class using the interface to implement the methods. Additionally the interface, like any class, can also be used as a data type and this is where the juju happens.
Instead of declaring the controller as a WiiController type, or a MouseController type, it’s defined as the interfaces type: IController. By convention, interface names begin with a I. So, the code previously shown becomes:

public class Engine extends Sprite
{	
	private var controller:IController;
 
        public function Engine()
	{			
		controller = new WiiController(); 
        }
        private function gameLoop(e:Event):void
	{				
		controllerIcon.setPosition(controller.getPosition());			
	}

Everything is the same, except the initial declaration of the controller variable. If you now decide to use the mouse you’d only change the one line in the constructor to:

controller = new MouseController();

and everything will still work. Because both WiiController and MouseController implement IController:

public class MouseController implements IController
public class WiiController implements IController

IController itself being simply:

public interface IController
{		
	function getPosition():Point;
	function getTilt():Number;
        function get trigger():String;
}

So back to the original point – if you program to an interface then it’s much easier to make modular code.

UPDATE: Since I started this post I stopped using WiiFlash and it’s server – as the server is still a little buggy. I got crashes quite ofteh when turning wii remote off while the server was running. Now, I’m using GlovePIE which works great – 3 lines of pie script and you can use a Wii remote for your mouse. In fact you can use a PS3 controller, a joystick, etc. and it’s not limited to the mouse you can use a joystick to do keyboard input… Cool shit.

Category: OOP  | Comments off
Monday, January 26th, 2009 | Author: Dave

For a long time I’ve been working to expand my OOD skills, and have read many articles, blogs and a few books. Head First Design Patterns is great, by the way. Anyway, one concept that you will come across repeatedly is that of encapsulating what varies.

Have a look at the following getUsers() method – this is a method from an AMFPHP service class that simply returns the data, for a given user, from a MySQL users table to Flash:

function getUser($id)
{	
        $sql = "SELECT * FROM users WHERE id=$id";
 
	$result = mysql_query($sql, $connector);
	if(mysql_num_rows($result) != 0){
		return mysql_fetch_array($result);
	}else{
		return -1;
	}
}

Simple enough. However, in a typical system you will have dozens of services and most of those services will have multiple methods – eg. to save, update and delete data as well. So, what happens when your shiny new system is installed on a server running PostgreSQL? Answer: You spend days changing API calls if your code looks like the above. And then you have two versions of your services. The problem is that you’ve programmed your services to work only with the MySQL API methods.

So how do you fix it? You encapsulate what varies – the database API calls. If you stick the database access stuff into its own class, and then access everything through your new database class, you remove the tight coupling you have to MySQL. If you need to change the database API calls, you only have to change one class, not the potentially hundreds that may use it. Let’s take a look at a modified version of the above method:

var $myDB;
$this->myDB = new DBAccess(); //create an instance of the DBAccess class
 
function getUser($id)
{	
	$sql = "SELECT * FROM users WHERE id=$id";
 
	$result = $this->myDB->query($sql);
	if($this->myDB->num_rows($result) != 0){
		return $this->myDB->fetch_array($result);
	}else{
		return -1;
	}
}

And over in your DBAccess class you’d define the query(), num_rows() and fetch_array() methods, along with any other database related functionality:

<?PHP
 
	class DBAccess
	{					
		function DBAccess(){}		
 
		function query($sql)
		{
			return mysql_query($sql, $this->getConnection());
		}
 
		function num_rows($result)
		{
			return mysql_num_rows($result);
		}
 
		function fetch_array($result)
		{
			return mysql_fetch_array($result);
		}		
 
		function getConnection(){			
			$con = mysql_connect("localhost", "DBUSER", "USERPASSWORD");
			mysql_select_db("DATABASENAME", $con);					
			return $con;
		}
	}
?>

If you change over to PostgreSQL you need only to modify DBAccess.php. And taking it a step further, you could put in switch statements enabling the class to use various databases.

Category: OOP  | Comments off