The Null Object Pattern – Polymorphism in Domain Models

Tweet

While certainly a far cry from being canonical, it can be said that Orthogonality is the quintessence of software systems that rest on the foundations of “good design”, where the constituent modules are neatly decoupled from one another, making the system less vulnerable to rigidity and fragility issues. Of course, it’s easier to chatter on about the benefits that orthogonal systems than getting an actual system up and running in production; the process is often a pursuit of utopia.

Even though, the implementation of highly-decoupled components in a system is everything but a utopian concept. The use of several programming concepts, such as Polymorphism, permit one to design flexible programs whose parts can be switched over at runtime and whose dependencies can be expressed in the form of abstractions rather than concrete implementations. I’d dare say the old “Programming to Interfaces” mantra has gained ubiquitous adoption over time, regardless of if we’re talking about implementing infrastructure or application logic.

Things, however, are radically different when stepping on the terrain of Domain Models. And to be frank, this is a predictable scenario. After all, why should a web of interconnected objects, whose data and behavior are constrained to well-defined business rules, be polymorphic? It doesn’t make much sense per se. There are a few exceptions to this rule, though, that might be eventually applicable to this case in particular.

The first exception is the use of Virtual Proxies, which effectively share the same interface as the one implemented by the actual domain objects. The other exception is the so-called “Null Case”, a special situation where an operation might end up assigning or returning a null value instead of a nicely populated entity. In a traditional, non-polymorphic approach, the consumer of the model must check for these “evil” nulls and handle the condition gracefully, thus generating an explosion of conditionals throughout your code.

Fortunately, this seemingly-tangled situation can be sorted out simply by creating a polymorphic implementation of the domain object, which would implement the same interface as the one of the object in question, only that its methods wouldn’t do anything, therefore offloading client code from doing repetitive checks for ugly null values when the operation is executed. Not surprisingly, this approach is a design pattern called Null Object, which takes the advantages of Polymorphism to extremes.

In this article I’ll demonstrate the pattern’s benefits in a few situations and show you how sweet they cling to a polymorphic approach.

Handling Non-Polymorphic Conditions

As one might expect, there are several paths to tread when showcasing the niceties of the Null Object pattern. One that I find particularly straightforward is the implementation of a data mapper which may eventually return a null value from a generic finder. Let’s say that we’ve managed to create a skeletal domain model made up of just one single user entity. The interface, along with its class, look like this:

<?php
namespace Model;

interface UserInterface
{
    public function setId($id);
    public function getId();
     
    public function setName($name);
    public function getName();
    
    public function setEmail($email);
    public function getEmail();
}
<?php
namespace Model;

class User implements UserInterface
{
    private $id;
    private $name;
    private $email;

    public function __construct($name, $email) {
        $this->setName($name);
        $this->setEmail($email);
    }
    
    public function setId($id) {
        if ($this->id !== null) {
            throw new BadMethodCallException(
                "The ID for this user has been set already.");
        }
        if (!is_int($id) || $id < 1) {
            throw new InvalidArgumentException(
              "The ID for this user is invalid.");
        }
        $this->id = $id;
        return $this;
    }
    
    public function getId() {
        return $this->id;
    }
    
    public function setName($name) {
        if (strlen($name) < 2 || strlen($name) > 30) {
            throw new InvalidArgumentException(
                "The user name is invalid.");
        }
        $this->name = $name;
        return $this;
    }
    
    public function getName() {
        return $this->name;
    }
    
    public function setEmail($email) {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new InvalidArgumentException(
                "The user email is invalid.");
        }
        $this->email = $email;
        return $this;
    }
    
    public function getEmail() {
        return $this->email;
    }
}

The User class is a reactive structure which implements some mutators/accessors in order to define the data and behavior of a few users.

With this contrived domain class in place, now we can go a step further and define a basic Data Mapper which will keep our domain model and the data access layer isolated from each other.

<?php
namespace ModelMapper;
use LibraryDatabaseDatabaseAdapterInterface,
    ModelUser;

class UserMapper implements UserMapperInterface
{   
    private $adapter;
    
    public function __construct(DatabaseAdapterInterface $adapter) {
        $this->adapter = $adapter;
    }
    
    public function fetchById($id) {
        $this->adapter->select("users", array("id" => $id));
        if (!$row = $this->adapter->fetch()) {
            return null;
        }
        return $this->createUser($row);
    }
    
    private function createUser(array $row) {
        $user = new User($row["name"], $row["email"]);
        $user->setId($row["id"]);
        return $user;
    }
}

The first thing that should have popped out is that the mapper’s fetchById() method is the naughty boy on the block as it effectively returns a null if no user in the database matches the given ID. For obvious reasons, this clunky condition makes the client code go through the hassle of checking for the null value every time the mapper’s finder is called.

<?php
use LibraryLoaderAutoloader,
    LibraryDatabasePdoAdapter,
    ModelMapperUserMapper;
    
require_once __DIR__ . "/Library/Loader/Autoloader.php";
$autoloader = new Autoloader;
$autoloader->register();

$adapter = new PdoAdapter("mysql:dbname=test", "myusername", "mypassword");

$userMapper = new UserMapper($adapter);

$user = $userMapper->fetchById(1);

if ($user !== null) {
    echo $user->getName() . " " . $user->getEmail();
}

At first glance that wouldn’t be much of an issue, so long as the check is done in a single place. But wouldn’t you hit your head against a brick wall if the same lines appear across multiple page controllers or inside a service layer? Before you know it, the seemingly-innocent null returned by the mapper produces a plague of repetitive conditions, an ominous sign of bad design.

Removing Conditionals from Client Code

There’s no need for anguish, however, as this is exactly the kind of case where the Null Object pattern shows why Polymorphism is a godsend. If we want to get rid of those pesky conditionals once and for all, we can implement a polymorphic version of the previous User class.

<?php
namespace Model;

class NullUser implements UserInterface
{
    public function setId($id) { }
    public function getId() { }
    
    public function setName($name) { }
    public function getName() { }
    
    public function setEmail($email) { }
    public function getEmail() { }
}

If you were expecting a full-fledged entity class packaging all sort of bells and whistles, I’m afraid you’ll mighty disappointed. The “null” version of the entity conforms to the corresponding interface, but the methods are empty wrappers with no actual implementation.

While the existence of the NullUser class apparently doesn’t buy us anything useful to praise, it’s a neat creature that allows us to throw all the previous conditionals into the trash. Want to see how?

First and foremost, we should do some up front work and refactor the data mapper so its finder returns a null user object instead of the null value.

<?php
namespace ModelMapper;
use LibraryDatabaseDatabaseAdapterInterface,
    ModelUser,
    ModelNullUser;

class UserMapper implements UserMapperInterface
{   
    private $adapter;
    
    public function __construct(DatabaseAdapterInterface $adapter) {
        $this->adapter = $adapter;
    }
    
    public function fetchById($id) {
        $this->adapter->select("users", array("id" => $id));
        return $this->createUser($this->adapter->fetch());
    }
    
    private function createUser($row) {
        if (!$row) {
            return new NullUser;
        }
        $user = new User($row["name"], $row["email"]);
        $user->setId($row["id"]);
        return $user; 
    }
}

The mapper’s createUser() method hides a tiny conditional as now it’s responsible for creating a null user whenever the ID passed into the finder doesn’t return a valid user. Even so, this subtle penalty not only saves client code from doing a lot of repetitive checks, but turns it into a permissive consumer which doesn’t complain when it has to deal with a null user.

<?php
$user = $userMapper->fetchById("This ID is invalid...");

echo $user->getName() . " " . $user->getEmail();

The major pitfall with this polymorphic approach is that any application consuming it would become too permissive, as it’d never crash when working with invalid entities. In the worst case, the user interface would display just a few blank lines here and there, but nothing really noisy to make us cringe. This is particularly evident when scanning the current implementation of the earlier NullUser class.

Even though, it’s feasible, not to say recommended, to encapsulate logic in null objects while keeping its polymorphic nature untouched. I’d even say that null objects are great candidates for encapsulating default data and behavior that should be only exposed to client code in a few special cases.

If you were ambitious enough and wanted to give this concept a try using naïve null user objects, the current NullUser class could be refactored in the following way:

<?php
namespace Model;

class NullUser implements UserInterface
{
    public function setId($id) { }
    public function getId() {
        return "The requested ID does not correspond to a valid user.";
    }
    
    public function setName($name) { }
    public function getName() {
        return "The requested name does not correspond to a valid user.";
    }
    
    public function setEmail($email) { }
    public function getEmail() {
        return "The requested email does not correspond to a valid user.";
    }
}

The enhanced version of NullUser is slightly more expressive than its quiet predecessor now that its getters provide some basic implementation to return a few default messages when an invalid user is requested.

Although trivial, this change has a positive impact in the manner that client code processes null users, as this time the consumers have at least a clear idea that something went wrong when they attempted to pull in a non-existent user from storage. That’s a nice breakthrough, which shows not only how to implement null objects that actually aren’t null at all, but also how easy it is to move logic inside the objects in question according to specific requirements.

Closing Remarks

Some might say that going through the hassle of implementing null objects is overkill, especially in PHP where central OOP concepts, such as Polymorphism, are blatantly underrated. They’d be right to some extent.

Even though, the progressive adoption of well-trusted programming principles and design patterns, along with the level of maturity currently reached by the language’s object model, provides all of the groundwork necessary for moving forward with firm steps and starting to use a few little “luxuries” which were considered tangled, impractical concepts not so long ago. The Null Object pattern falls under this category, but its implementation is so straightforward and elegant that it’s hard not to find it appealing when it comes to cleaning up client code from repetitive null value checks.

Image via Fotolia

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • lingtalfi

    Nice article, thanks for sharing. I’ll try to use it when appropriate.

    • Alex Gervasio

      Hey,
      Thanks for the compliments. Glad to know the post has been informative.

  • Den

    Alex, very interesting. Validation part of class User was removed … I think it must be in createUser method, is n’t it?

    • Alex Gervasio

      Hey Den,
      Thanks for the kind comments. I don’t know exactly what you mean, but validation in mutators of the User class is just there. It hasn’t been removed at all. Make sure to double check the class’ implementation and you’ll see it. Thanks again for the feedback.

  • http://3dwebtech.gr κατασκευη ιστοσελιδας

    nice article for learning php coding. thanks

    • Alex Gervasio

      Good to hear that indeed. Thanks for the comments.

  • Richard

    I don’t think anyone would complain if you focused more on explaining the concepts at hand in a clear and expressive way than trying to come off as some super smart dude. The first few paragraphs are nothing but barriers of entry.

    Regardless, thank you for taking the time to share this.

  • Richard

    To be fair, I should at least comment on my thoughts of the Null Object pattern. While it’s neat and useful in theory, it is a massive violation of DRY (Don’t Repeat Yourself). In setting up various Null classes you’ll have to also map every method that the normal class would have. All of that just to remove a few conditionals just isn’t worth it in my opinion. Not to mention, type checking is an important thing to do in defensive programming and a good habit to have. I tend to chalk up NOP under “cool but impractical.”

    • Alex Gervasio

      To be fair, I never wanted to look as a super smart dude. If the introductory paragraphs aren’t clear enough, or ever tainted with a pinch of ambiguity, well, sorry about that. Regarding your opinion on that the Null Object pattern is a breakage of DRY, I completely disagree. Null Objects are usually scarce, utilized in just a few special use cases, where their implementation can save you from doing a lot of REPETITIVE check for null values (which effectively is a DRY violation).
      As I said in the wrapping thoughts, the use of Null Objects is rather a luxury at least in the PHP world (in more complex, enterprise-level scenarios, can be a real blessing, trust me), which should be used only when you think is going to improve the efficiency of your design through the benefits of Polymorphism. If that’s not your case, then simply let your pragmatic side out and use plain old conditionals. Thanks for the insights.

    • amn

      Do you have any real examples of this? I’m finding it difficult to imagine it being useful in any situation.
      If you have a lot of conditional checks, then you can just make a big generic check first. For example, check if you found the model in the controller first and then process it there. Don’t even let it get to the view to display the name/email data if you didn’t find it; redirect to another page or show an error message instead.

      • Alex Gervasio

        Yes. Not so long ago we refactored an old project whose search module was literally a mess of spaghetti code, plagued with tons of conditionals which checked at multiple places if the queries issued by users returned some valid domain object(s). We refactored the entire module, centralized all the checking in a thin service layer, which when the search was unsuccessful, returned a null object containing some basic logic. In its current state, the object in question is embedded straight into the view, which doesn’t have to be concerned about what type of object is dispatched by the service. Of course, the implementation required a little bit more of effort, but in perspective the payback was worthwhile, as we managed to get a nice polymorphic search module up and running, not to mention the removal of the previous clunky conditionals. Sweet and nice :).

  • Uncle Fred

    I have seen and probably implemented some repetitive conditionals myself. And the worst ting was: I didn’t even know it was a code smell. Still, my pragmatic side says: 1. I just retrieved an object and now I still need to check whether its a Null Object or a “real” entity. 2. The messages from the Null Object would not fit all purposes and would need to be replaced.
    On the positive side: I learned the Null Object pattern and I read another great article. Yes, and you don’t come across as a “trying to be a clever dude” to me.

    “the mapper’s fetchById() method is the naughty boy on the block” I chuckled :)

    • Alex Gervasio

      Hey Fred,
      Thanks for the comments. By no mean I’m saying that a few conditionals are code smell at all. How would you get your programs up and running without appealing to them, regardless of if you’re “pragmatic” or not? It doesn’t make any sense. The actual, harmful code smell is the proliferation of a LOT of conditionals scattered through the code. The beauty of OOP is that you can take advantage of the niceties provided by Polymorphism and exploit them for eliminating those bunch of conditionals in an efficient and elegant fashion. Null Objects (even those which carry both state and logic) are a glaring example of this virtue in action.
      Unquestionably, PHP isn’t the most fertile soil for using Null Objects, just because the implementation of complex, rich domain models is extremely scarce. The real benefits of the pattern emerge with huge, domain models that carry a lot of business logic, exposing complex webs of relationships, and where it’s necessary to do lots of repetitive null checking, or eventually check for some other value over and over. Null objects are a fantastic way for cleaning up dirty client code from those conditionals, even if their implementation in PHP might be incidentally overkill (in Java and C++, Null objects have a much more ubiquitous presence).
      Even when the pattern admittedly has its good and bad facets, just like any other pattern out there, the morale of the story here is simple -yet fundamental: use Polymorphism whenever possible, because is a fundamental OOP pillar, which will let you get rid of conditionals in an effective way, not to mention it will make your application more orthogonal, based on abstractions (read interfaces) rather than on concrete, rigid implementations. That’s an OOP cornerstone I’d like to see more often in PHP, even when there’re several concrete breakthroughs in that direction.
      By the way, did you find the old “naughty boy on the block” cliché fun? Yep, my creativity sometimes blows me away :) Thanks for the positive feedback.

  • lingtalfi

    Another useful usecase of this pattern is logging.

    interface LoggerInterface
    {
    public function log($message);
    }

    class NullLogger implements LoggerInterface
    {
    public function log($message)
    {

    }
    }

    class MyClass
    {
    private $logger;

    public function __construct(LoggerInterface $logger = null)
    {
    if (null === $logger) {
    $logger = new NullLogger();
    }
    $this->logger = $logger;
    }

    public function anyMethod()
    {
    if (true === false) {
    $this->logger->log(“boo”);
    }
    }

    }