Home » Code » Implementing The Specification Pattern

Implementing The Specification Pattern

Posted by on August 25th, 2014

Implementing The Specification Pattern
Last week we looked at encapsulating business logic within Value Objects. By using the characteristics of Object Oriented Programming we can maintain the integrity of our business rules within the harmony of using plain old PHP objects.

One of the rules that we needed to implement last week was the uniqueness of a user’s username and email address. This kind of validation can’t fit inside a Value Object because it needs to be able to check the database for existing records.

Instead of coupling the Value Object to the storage mechanism, we can instead use The Specification Pattern to check for uniqueness.

In this week’s tutorial we’ll look at applying The Specification Pattern to encapsulate the business rules of object selection within our applications.

The problem we are trying to tackle

Before I jump into the weeds of explaining The Specification Pattern and implementing it in code, first I’ll briefly clarify the problem we are trying to tackle.

Last week we created an Email Value Object to work with email addresses within Cribbb. We can ensure that email addresses are valid by defining the rule within the constructor of the class:

// This will throw an exception
$email = new Email('not a valid email address');

This is great, but we also need to ensure that the email address hasn’t already been registered.

The uniqueness business rule is very important within the context of our application, but it cannot be satisfied by our simply Value Object because we need to query the data storage to see if the email address already exists.

The Email Value Object does not know anything about data storage, and so we need another way of encapsulating this business rule.

What is The Specification Pattern?

The Specification Pattern is a way of encapsulating business rules to return a boolean value. By encapsulating a business rule within a Specification object, we can create a class that has a single responsibility, but can be combined with other Specification objects to create maintainable rules that can be combined to satisfy complex requirements.

The Specification object has a single public isSatisfiedBy() method that will return a boolean value:

class UsernameIsUnique implements UsernameSpecification {
  /** @return bool **/
  public function isSatisfiedBy(Username $username)
  {
    //
  }
}

The UsernameIsUnique Specification object can be implemented using whatever means necessary. In this example you would likely inject a repository to query the database to check if the username was indeed unique.

Why would you choose to use The Specification Pattern

The Specification Pattern is powerful because it allows you to encapsulate the business rule inside of the class whilst providing an easy to use API that can be consumed within your application.

By using The Specification Pattern, you can use the Specification Object anywhere that is necessary in your application. Your application does not need to know how the business rule is enforced because it is internal to the Specification object. If the business rules is changed, you only have to change that single source of truth.

Using The Specification Pattern also makes having alternative, or multiple rules easier to work with. By encapsulating each rule as a Specification object you are free to use many instances together to satisfy the complex requirements of the organisation without getting bogged down in complex or unmaintainable code.

Writing the Username Specification tests

The first thing I will do will be to write the tests for UsernameIsUnique specification object.

Create a test file with the following structure:

<?php namespace Cribbb\Domain\Model\Users;

use Mockery as m;

class UsernameIsUniqueTest extends \PHPUnit_Framework_TestCase {

}

Next write a setUp() method so we don’t have to instantiate a new instance of the object for each test:

public function setUp()
{
  $this->repository = m::mock('Cribbb\Domain\Model\Users\UserRepository');
  $this->spec = new UsernameIsUnique($this->repository);
}

I’m going to be using a repository to query the database so I can inject a mock to satisfy that requirement. Note, the repository doesn’t actually exist yet, but I know it’s going to implement an interface so I can just stick that in for now.

Next I can write my two tests, one where the repository returns null and one where the repository returns a result in order to mock finding an existing user or not:

/** @test */
public function should_return_true_when_unique()
{
  $this->repository->shouldReceive('userByUsername')->andReturn(null);
  $this->assertTrue($this->spec->isSatisfiedBy(new Username('430r0923r0209rjw')));
}

/** @test */
public function should_return_false_when_not_unique()
{
  $this->repository->shouldReceive('userByUsername')->andReturn(['id' => 1]);
  $this->assertFalse($this->spec->isSatisfiedBy(new Username('hello_world')));
}

Now if you give phpunit a blast you should see those tests failing.

Implementing The Specification pattern

The first thing I will do to implement The Specification pattern will be to create a UsernameSpecification interface:

<?php namespace Cribbb\Domain\Model\Users;

interface UsernameSpecification {

  /**
   * Check to see if the specification is satisfied
   *
   * @return bool
   */
  public function isSatisfiedBy(Username $username);

}

We’re probably going to need multiple specification objects and so it’s good practice to define an interface so that each implementation abides by the same contract.

Next we can create the UsernameIsUnique specification object:

<?php namespace Cribbb\Domain\Model\Users;

class UsernameIsUnique implements UsernameSpecification {

  /**
   * @var UserRepository
   */
  private $repository;

  /**
   * Create a new instance of the UsernameIsUnique specification
   *
   * @param UserRepository $repository
   */
  public function __construct(UserRepository $repository)
  {
    $this->repository = $repository;
  }

  /**
   * Check to see if the specification is satisfied
   *
   * @param Username $username
   * @return bool
   */
  public function isSatisfiedBy(Username $username)
  {
    if($this->repository->userByUsername($username)
    {
      return false;
    }

    return true;
  }

}

In this class I’m injecting a repository that implements the UserRepository interface and then setting it as a property of the class.

Next I’m implementing the isSatisfied() method by searching the database for a user that has that username. If a record is returned we can return false because the username is not unique, otherwise we can return true.

Now if you run the tests again they should all pass!

As with last week’s tutorial, I won’t go into how to implement the code to check if an email is unique as it is essentially exactly the same as the code in this tutorial. If you get stuck you can always check my GitHub repository.

Conclusion

In today’s tutorial we’ve looked at how to encapsulate the business rules of object selection within our applications. Instead of coupling objects together, or adding extra responsibility to existing classes, we can create single responsibility specification objects that can be combined together to give us the flexibility to meet complex and critical business rules.

As with last week’s post, this tutorial was heavily inspired by the excellent talk Unbreakable Domain Models by Mathias Verraes. If you haven’t already watched this talk, I highly recommend you do so today!

This is a series of posts on building an entire Open Source application called Cribbb. All of the tutorials will be free to web, and all of the code is available on GitHub.

To view a full listing of the tutorials in this series, click here.

Philip Brown

Hey, I'm Philip Brown, a designer and developer from Durham, England. I create websites and web based applications from the ground up. In 2011 I founded a company called Yellow Flag. If you want to find out more about me, you can follow me on Twitter or Google Plus.

  • Gayan Hewa

    Pure awesome timing, it was just last week I looked into the Specification pattern over someones recommendation from the laravel.io IRC. I am pretty sure readers will find this github repo ( https://github.com/domnikl/DesignPatternsPHP ) complementing this article.

  • DenisGeorgiev

    Link for encapsulating business logic within Value Objects is broken

  • Pingback: The User Entity and The Ubiquitous Language | Culttt()

  • Right after the “Implementing The Specification pattern” title, the interface name is missing an E at the end of Username.

    Great post!

    • Oops, thank you Ramiro :) I’ll get that fixed :)

  • Pingback: What are the benefits of using Repositories? | Culttt()

  • Pingback: Implementing Domain Events | Culttt()

  • Pingback: Creating a User Registration Domain Service | Culttt()

  • alireza Rahmani khalili

    I’d like it but there is typo . this userByUsername(Username $username) should change to userByUsername($username)

  • Pingback: Creating and Using a Command Bus | Culttt()

  • Pingback: Failing Domain Rules and Validating User Input | Culttt()

  • nullcat

    Great post, thanks! But i have one question: if there will be muiltiple specifications for many entites (not only username, but email for example, etc), don’t we need interface that contains isSatisfiedBy method signature, because it is same for all specifications?

    • No I would use an interface for each type of specification, e.g isSatisfiedBy(Username $username), isSatisfiedBy(Email $email), rather than for all specifications.

      I think all Username specifications are of one type, and all Email specifications are of another type, but you wouldn’t really intermix them so I don’t think they should share the same interface.

  • Xu Ding

    A more detailed explanation of Specification pattern by Eric Evans and Martin Fowler. Hope you guys found it useful http://www.martinfowler.com/apsupp/spec.pdf

    • Thank you :) Eric and Martin are have a lot to teach us :)

  • Supersam

    A really great post. As I read this I wonder how to apply this to enumerators like user status? Would you inject it like an Assertion value object or would you create a specification e.g. isUserStatus($value) or do enumerators stand on their own? An example:

    /**
    * Create status object for user
    *
    * @param string $value
    */

    public function__construct($value)
    {
    // UserStatus would be created as an enumerator class with a set of constants e.g const ‘ACTIVE’ = 1;
    // EnumValue::isEnum checks to see if it is a string or numeric and then converts to check against the enum

    $this->value = UserStatus::get( EnumValue::isEnum($value, UserObjective::class ) )->getValue();

    }

    • Hmm, yeah I guess so. I usually only really use the specification pattern when I either need to query an external source (like a database) or if I need to create complex rules by combining different specifications together.

  • ricbra

    Thanks for this excellent blog post!

  • John Hall

    Great article! It does raise a question for me, as I’ve always defaulted this sort of thing to the database because it is so easy to implement there for simple objects.

    For example, in my abstract Repository class, I wrap the flush() method (or whatever triggers the insert/update) in a try/catch block which sends any caught Exception off to a handlePersistException() method, if the concrete class implements it. In that method, I can check if the Exception is an instance of Doctrine’s UniqueConstraintViolationException then I can re-throw the Exception with some nicely formed message (e.g., username ‘onecooldude’ is already taken, usernames must be unique).

    I think the Specification Pattern is great; it adheres beautifully to single responsibility and offers extreme reusability. However for a simple object with a single unique property, would you still implement the Specification Pattern as opposed to letting the database complain and handling the exception accordingly?

    Just wondering your personal preference on this one! Thanks again for an excellent and informative series!

    • Yeah for something that unique usernames I always have that kind of thing as business logic. The database complaining is usually always a last resort, and probably a problem with my business logic if it happens at all!

      • John Hall

        Thanks for the response Philip!