Creating a PHP Subclassed Singleton to Apply Fowler’s “Introduce Null Object” Refactoring

I found a need to implement the “Introduce Null Object“ refactoring procedure that is outlined in the  Refactoring book by Martin Fowler.

At first I wondered whether or not this refactoring is as applicable to PHP as it is to Java. After all, (as far as i can tell) in Java everything is an object whereas PHP offers a wider palette of in-built data types.

After much thought, I decided to give it a go and create my own NULL object.

A NULL Object is basically an instance of a class (that you define) that can represent an object that has a null value in a field. It is something that can be used to reduce the amount of times you need to check “if something is an object” before getting on with some logic.

A Null value and a null object are different things.

The null object is a contrived thing that you define. Whereas a null value represents, well… nothing.

In the example below, our null object is the NullAdvert subclass of the Advert class.

Our null object goes to the same nightclubs as its more fuller bodied parent without much trouble at the door. Whereas, a null value doesn’t even bother going to clubs. “What’s the point?”, it says, “No one would chat to me anyway”.

When you Might Use a Null Object

Say, for example,  you have applied the “Replace Data Value with Object” technique and you had an ”advert object” that used a magic __toString() method when it is echoed. This might notify any other objects observing it that it is being ‘echoed’ in a view script. (Useful for logging an impression, for example).

Example Without a Null Object

Without a Null Object getAdSlotContent()  either returns NULL value or an object. Which means, later in the code, you always have to be checking if you have an object at all before using it:

————–
<?php
//MyViewScript.phtml
….
//returns either NULL or $advert_obj:
$this->view->advert_obj = $adServer_obj->getAdSlotContent(’Banner468×60′);

…later in code…

<?php if ((is_object($this->view->advert_obj)) && ($this->view->advert_obj->hasValue()))  : ?>

<div id=”Banner468×60Slot”>

<?php

echo  $this->view->advert_obj; //triggers toString() magic method
?>
</div>

<?php endif ?>

//…more layout html…
—————

Example With a Null Object

If you can make getAdSlotContent() always return ‘an object’. You can just use it, call its methods. If it is a NULL Object it would just have NULL’ish behaviour.

———-

<?php
//MyViewScript.phtml
//returns either a “NULL $advert_obj” OR
//$advert_obj
:
$this->view->advert_obj = $adServer_obj->getAdSlotContent(’Banner468×60′);

…later in code…
<?php if ($this->view->advert_obj->hasValue()) : ?>

<div id=”Banner468×60Slot”>

<?php

echo  $this->view->advert_obj; //triggers toString() magic method
?>
</div>

<?php endif ?>
//…more layout html…

——–

As long as the hasValue() method of the NullAdvert class  always returns FALSE then the script will be OK.

———

Adding  the Singleton into the Mix

Fowler recommends that the singleton pattern is used to define the NULL Object to ensure that only one instance of the class exists (thus preventing a plethora of these things being created throughout the system).

So this made me wonder:

How could I implement a singleton as a subclass of a non-singleton class?

Well, you can find the answer in a comment by “k at” on the php site:
http://www.php.net/manual/en/language.oop5.patterns.php#86323

(I did not bother to write out examples of the classes in this blog post - cos it is relatively easy to determine by following the link above. I had not planned to make it a lengthy case study of the Introduce Null Object refactoring - which it seems to have become. If you are interested and what to see more examples , add a comment and I will elaborate this post. )

Example With a Null Object AND Seeing some extra benefits

Ok - so now that an object (with a guaranteed interface)  is always returned from our adserver’s getAdSlotContent() method we can drop the assignments elsewhere on the code and just call it directly where needed. This is an example of an Inline Temp refactoring. Inline Temp opens doors to many other refactorings that can really make the code ’speak for itself’.

———-

<?php
//MyViewScript.phtml

/*
This can be now be removed
//returns either a “NULL $advert_obj”, OR
//$advert_obj
$this->view->advert_obj = $adServer_obj->getAdSlotContent(’Banner468×60′);
*/

…later in code…
<?php if ($adServer_obj->getAdSlotContent(’Banner468×60′)->hasValue()) : ?>

<div id=”Banner468×60Slot”>

<?php

echo $adServer_obj->getAdSlotContent(’Banner468×60′); //triggers toString() magic method
?>
</div>

<?php endif ?>
//…more layout html…

——–

So, now I could copy a chunk of this view script into a new one without having to spend much time scanning around for arbitrary assignments in the code above. It is now free.

——–

Leave a Reply