PHP Near Strategy Design Pattern Part I: No Conditionals, Please

nearStratWhy ‘Near’ Strategy?

The Strategy design pattern is important because it is so useful, and two different posts on this blog have covered it in the past. What I would like to do with this implementation of the pattern is to do two things: 1) First, show how to create operations that require no conditional statements, and 2) Second, (in Part II) show the role of the Context participant. In this first part, I’d like to look at the HTML->PHP operations where specific objects (classes) can be called through HTML forms.

One of the nice things about the Strategy pattern is that the logic of it is very easy to understand; albeit on a foundational level. You have different tasks, and each task requires a different algorithm; so why not separate the algorithm operations into distinct objects (classes) and loosely bind them to the client? Each class will only do one thing, and that is to carry out an algorithmic operation. To do this, start off with a “Near Strategy”–a pseudo-patten: the Strategy design pattern missing the Context. Figure 1 shows the difference between a Near Strategy and true Strategy design pattern:

Figure 1: The Near Strategy design and the Strategy Design pattern

Figure 1: The Near Strategy design and the Strategy Design pattern

The HTML UI and the Client are not a part of the Strategy design pattern, but in this example, both are required for making requests. Before going on, try out the program by clicking the Play button and download all of the files.

PlayDownload

You can use the files “as-is” but you will need to change the IConnectInfo.php file so that the hostname (HOST), user name (UNAME), database name (DBNAME) and password (PW) is your actual MySql database. Also, once you create a table with a name of your choosing, be careful not to create it again if you want to keep your data entered into the table!

Using Form Names for Concrete Strategy Names

One of the coolest features of PHP is the ability to use strings to create instances of classes (aka: objects). For example,

$myVar = “MyClass”;
$myObject = new $myVar();

creates an instance of the class, MyClass. Knowing this, we can create the class names in HTML as form values. For instance:




The selected radio button value can be passed in a super-global to PHP:


$myVar = $_POST[‘callme’];
$myObject = new $myVar();

Using this, the Client doe not have to work through conditional statements to decide which request to fulfill. Like the Strategy design pattern, even the Client is free from using conditional statements as can be seen in the following listing:


function __autoload($class_name) 
{
    include $class_name . '.php';
}
Class Client
{
    private $chooser;
    private $instance;
 
    public function __construct()
    {
        $this->chooser=$_POST['sql'];
        $object=$this->chooser;
        $this->instance=new $object();
    } 
}
$worker=new Client();
?>

As you can see the Client class is pretty simple with no conditional statements. It takes the value of the radio button send with a Post method. The radio button group is named “sql”; so whatever button is clicked is translated into an object.

What’s Wrong with Conditional Statements?

Previous posts on Strategy patterns have examined the advantages of not having conditional statements in a program. The main point is that making changes with a lot of conditional statements to refactor is prone to bugs and a lot more work. On the Web, you can find a plethora of posts on why not to use conditional statements if at all possible. (See an example here.)

Another reason for avoiding conditional statements in algorithmic thinking is for developing more elegant and efficient algorithms. An example was discussed in a post on moving SVG graphics that employed a modular arithmetic algorithm instead of conditional statements. If you approach a problem and ask,

How can this be solved without conditional statements?

you’ll be on the road to better algorithms. Nested conditionals are even more entangling and are in dire need of a better algorithms. This is not to say to never use conditionals, but if you can avoid them, try. The Strategy and State design patterns are a good place to start.

The Strategy Interface

The interface used is appropriately named, NearStrategy because it’s not an actual strategy. It is an abstract class with a single abstract protected method, doAlgorithm(). The protected properties are those that are used by all of the methods and help encapsulate all of the implementations of the interface (abstract class.)


abstract class NearStrategy
{
    //Properties all will use
    protected $hookup;
    protected $sql;
    protected $tableMaster;
 
    //Abstract method   
    abstract protected function doAlgorithm();
}
?>

Each of the different concrete strategies must implement the abstract method, but since it’s fairly general, that is not difficult. For example, take a look at the class for inserting data:


class Insert extends NearStrategy
{     
        //Field Variables
        private $name;
        private $email;
        private $purchase;
        private $money;
 
        public function __construct()
        {
                $this->tableMaster=$_POST['tableName'];
                $this->hookup=UniversalConnect::doConnect();
                //Uses real_escape_string() to make injection attacks
                //difficult
                $this->name=$this->hookup->real_escape_string($_POST['cusname']);
                $this->email=$this->hookup->real_escape_string($_POST['cusemail']);
                $this->purchase=$this->hookup->real_escape_string($_POST['purchase']);
                //floatval changes value from HTML string to floating point
                $this->money=floatval($this->purchase);
                $this->doAlgorithm();
                $this->hookup->close();   
        }
 
        protected function doAlgorithm()
        {
                $this->sql = "INSERT INTO $this->tableMaster
                (cusname,cusemail,purchase)
                VALUES ('$this->name','$this->email', '$this->money')";
 
                try
                {     
                        $this->hookup->query($this->sql);
                        printf("User name: %s 
Email: %s
and $%s have been inserted into %s."
,$this->name,$this->email,$this->money,$this->tableMaster); }   catch (Exception $e) { echo "There is a problem: " . $e->getMessage(); exit(); } } } ?>

This implementation of NearStrategy is simply the SQL statements within the PHP mysqli() method.(The $hookup variable contains the mysqli information.) Likewise, the Display class implements NearStrategy with different requirements but the same interface:


class Display extends NearStrategy
{
        public function __construct()
        {
                $this->tableMaster=$_POST['tableName'];
                $this->hookup=UniversalConnect::doConnect();
                $this->doAlgorithm();
                $this->hookup->close();   
        }
 
        protected function doAlgorithm()
        {
        //Create Query Statement
                $this->sql ="SELECT * FROM $this->tableMaster";
 
                try
                {
                        $result = $this->hookup->query($this->sql);
 
                        printf("Select returned %d rows.

", $result->num_rows); while ($row = $result->fetch_assoc()) {   printf("ID: %s Name: %s
Email: %s
Amount spent $%s

", $row['id'],$row['cusname'],$row['cusemail'],$row['purchase'] ); }   $result->close(); } catch(Exception $e) { echo "Here's what went wrong: " . $e->getMessage(); } } } ?>

As you can see, all that is required is the basic SQL information with the same try/catch exception striation but with different output.

Simplicity is the Key

After seeing PHP programs hundreds of lines long in the same file and/or with multiple nests in a conditional statement, I wonder why in the world anyone would think that OOP is difficult? An important distinction must be made between long and convoluted and “advanced.” Rather, think of “advance to simplicity.” OOP is all about objects communicating with one another, and each object generally has a single task. That’s pretty simple when you stop to think about it. Learning more PHP statements, better ways to keep data secure and do more things does not mean “advance.” It means doing the same thing over and over but with more terms and a better chance of becoming entangled. Design patterns are a relatively simple way out of the same old bad habits for better, and in the long run, easier programming.

Copyright © 2014 William Sanders. All Rights Reserved.

0 Responses to “PHP Near Strategy Design Pattern Part I: No Conditionals, Please”


  • No Comments

Leave a Reply