Saturday, December 29th, 2007
Create meaningful class attributes, not ambiguous arrays, in PHP
Happy holidays guys, it’s been a while since the last update, but I’ve been busy tweaking our framework at devproducts and wrappin’ presents that I’ve not had the time to actually make any valid posts aside from the odd I shopped here and there post, so I thought it would have been best to keep quiet until I had something meaningful to say.
A couple of years ago, when I had come across some code I had coded when I had first started learning OOP. I came across an object coined “DataSpace” from frameworks like WACT which used this uber-cool pattern.
Going through some of my old code, I’ve noticed some serious flaws. This “DataSpace” been applied wayyyy too liberally throughout almost all my applications.
At one point, my programming technique had somehow strayed from the path and I actually found myself abstracting actual properties or attributes of a class into an array which served as a generic container for properties and attributes.While this seemed neat at the time, doing things this way made the properties or attributes of the class very ambiguous. This also took away the structural description that an attribute or property would provide.
Here are a couple of examples.A person class coded using a properties array/key map as it’s sole property - very clever, it looks a little cleaner than the next example and also, we do not have to worry about adding extra attributes if we need them down the track but important parts are sacrificed. For example, say that we had it down that the Person class should have name, height, age and gender as its attributes. The convenience of this class is that the properties array is dynamic, all we need to do to add another “property” is to just add another $this->set(’weight’,$weight) to the mix.
class Person
{
protected $_attributes = array(); // name, height, age, gender
public function __construct($name,$height,$age,$gender)
{
$this->set(‘name’, $name);
$this->set(‘height’, $height);
$this->set(‘age’, $age);
$this->set(‘gender’, $gender);
}
public function get()
{
}
public function set($prop, $value)
{
}
}
?>
But there are some very important things that are sacrificed with this method. By having a dynamic properties array, there is no way we can express what the class structure will look like aside from the constructor’s parameters, ignoring the fact that this is a “workaround” for the limitation we injected by not havinga concrete set of attributes for our class, this method of describing structure through constructor parameters may become problematic - what if we have more than 4 attributes we need to set?
With a dynamic attributes array being used in place of the traditional type we’re going to run into so many dead ends that we’ll find ourselves giving up and realising that we cannot express the structure of the class with code alone, so we will have to rely on examples and documentation. But this too has it’s downfalls and chores, every time you change the class and add an attribute, you will need to update the documentation and/or example. Which defeats the convenience purposes we implemented this clever little class in the first place!
Let’s go crawling back to the old school way of doing things - using attributes to describe the structure of the class.
The preferred way of writing a class, the attributes make the structure of the class obvious - by looking at this example you will know at first glance that the Person class has name, height , age and gender as its attributes in contrast to the previous example where one may have to rely on a constructors parameter, documentation and/or code samples.
class Person
{
// protected $_attributes = array();
protected $_name;
protected $_height;
protected $_age;
protected $_gender;
public function __construct($name,$height,$age,$gender)
{
$this->_name = $name;
$this->_height = $height;
$this->_age = $age;
$this->_gender = $gender;
}
// getters
// settters
}
?>
Of course every time you add or remove an attribute you will have to add or remove getter and setter methods, but this is the only thing you will have to worry about. The class describes itself, each of the methods associated with the attribute or property makes sense.
To conclude, there’s a lesson in all this and that’s to keep your class attributes _AS_ attributes as opposed to a dynamic array of attributes. An attribute plays a major role in describing the structure of the class and should not be made dynamic - there’s more work in maintaining dynamic attributes, not to mention it opens the door to an “anything fits” scenario where our Person class can have attributes like “wheels” or “fences” and would still seem semantic to have them as the dynamic getter and setter methods allows this of course this could be prevented _with_ documentation but you shouldn’t have to.