31.2. Creating a utility class to construct CC BP charts

We will start from a high level and think about how we would like to be able to use such a utility class. Ideally it would be similar to other types of graphs classes. To keep things simple we want the following parameter to be adjustable

When doing designs like this it is always good to first write a small test driver without having to think about how to actually implement it. This keeps an end user perspective on things. Later on we can do changes if it turns out that a particular simplification for the user is simply too complex to implement.

So, lets think about how we (ideally) would like to be able to create the chart shown in Figure 31.3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
$graph = new CCBPGraph(300,250);
$graph->SetTitle('Buffer penetration','(history)');
 
$datax=array(83); $datay=array(60);
$datax_history = array(0,17,17,17,33,50,67,83); 
$datay_history = array(0,20,40,60,60,60,60,60);
 
$sp = new ScatterPlot($datay,$datax);
$sp->mark->SetType(MARK_DIAMOND);
$sp->mark->SetFillColor('white');
$sp->mark->SetSize(10);
 
$sp_hist = new LinePlot($datay2,$datax2);
$sp_hist->SetWeight(2);
$sp_hist->SetColor('black');
 
$graph->Add($sp_hist);
$graph->Add($sp);
 
$graph->Stroke();
?>

We cannot hope to have the class make it any simpler than this. This is as close to a "normal" line graph we can get (apart from the color indications in the background). So now its just a matter on designing this class.

Since the utility class will be a rather restricted graph class it with a very specific usage it doesn't make sense to implement it as an extension to the normal graph. Instead we will create contain class that contains a graph that we can modify and setup. (In UML language a has-a relation.)

We will name our utility class CCBPGraph (Short for Critical chain Buffer Penetration Graph). The class should have the following signature

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class CCBPGraph{ 
    private $graph = null ; // The real graph instance
 
    // The "normal" constructor
    public function __construct($aWidth,$aHeight) {}
 
    // Methods that will control the appearance
    public function SetTitle($aTitle,$aSubTitle) {}
    public function SetXMinMax($aMin,$aMax) {}
    public function SetYMinMax($aMin,$aMax) {}
    public function SetColorIndication($aSpec,$aColors=null) {}
    public function SetColorMap($aMap) {}
    
    // Internal function to create and setup the graph
    private function Init() {}
    
    // Mimix the standard graph functions Add() and Stroke()
    public function Add($aPlots) {}
    public function Stroke($aFile='') {}
}
?>

In addition the class must have a number of instance variables that are used to store the settings until we need them when we create the graph. However to keep things simple here we do not list them above. Lets now walk through the four groups of methods.

  1. The constructor

    public function __construct($aWidth,$aHeight) {}

    The constructor doesn't need to do very much. It just needs to store the user specified width and height so we get them back when we create the actual graph. We could also make use of the constructor to create an instance of the real graph class but we prefer to do as late as possible instantiation.

  2. Controlling the appearance of the graph.

    Again these methods will be very basic "setter" methods that will just store the user specified options until we need them when we construct the graph

    public function SetTitle($aTitle,$aSubTitle) {} 
    public function SetXMinMax($aMin,$aMax) {} 
    public function SetYMinMax($aMin,$aMax) {} 
    public function SetColorIndication($aSpec,$aColors=null) {}
    public function SetColorMap($aMap) {}

    For the color setter we should also add some basic error checking so that the parameter makes sense.

  3. The real worker method

    private function Init() {}

    Since this is the method is where we will do the actual work and will be fairly large we will spend the entire next section on this method.

  4. The "fake" standard methods. Add() and Stroke(). Since these are fairly short we will show them here in there entirety

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    <?php
    function Add($aPlots) {
        if( is_array($aPlots) ) {
            $this->iPlots = array_merge($this->iPlots,$aPlots);                
        }
        else {
            $this->iPlots[] = $aPlots;
        }
    }
        
    function Stroke($aFile='') {
        $this->Init();
        $this->graph->Add($this->iPlots);
        $this->graph->Stroke($aFile);
    }
    ?>

    When adding plots (with the Add() method) we have to take into account that the parameter can be either a single object or an array of plot objects (line and scatter plots) and we must handle that accordingly as is done above.

    For the Stroke() method we use this to call the initialization method (to actually create the graph) and then add the user specified plots and finally call the real Graph::Stroke() of the graph.

    These methods are very simple but from the outside it will look like a "real" graph class with a clean and simple interface.