Archive for the 'php' Category

Specifications for PHP5

php 6 Comments »

Only three months between posts. Not bad for me. For my sophmore blog entry I thought I’d share a PHP library implementing this idea by Evans and Fowler. Written for PHP5, it’s a library for defining custom specifications using composition and inheritance.

Let’s look at an example first to see what I’m talking about. Suppose you have a bunch of Person objects that look like this:

1
2
3
4
5
6
class Person {
    public $id;
    public $first_name;
    public $last_name;
    public $age;
}

Now let’s say you need to test them, looking for entities that are valid Person objects, are under 35 years old and have the last name “Johnson.” These conditions might be expressed like this…

1
$p->id >= 1 && $p->age < 35 && $p->last_name == "Johnson"

…and it would satisfy your requirements. But, what if you need this same piece of validation logic in another place? Or perhaps you have another validator that includes all these conditions but also checks to see if the person’s first name is “John?” You could repeat expression shown above, or you could create a specification to be re-used and extended.

1
2
3
4
5
6
7
8
9
class JohnsonSpecification extends AndSpecification {
    public function __constructor() {
        parent::__constructor(
            new AndSpecification(
                new GreaterOrEqualSpecification('id', 1),
                new LesserOrEqualSpecification('age', 34)),
            new EqualSpecification('last_name', 'Johnson'));
    }
}

What we have done here is create a binary tree of tests linked with AND operators to compose a complex specification that can be extended and re-used in our code. To validate a Person object, we would simply test the Person against our new specification:

1
2
3
4
5
6
7
$spec = new JohnsonSpecification();
 
if ($spec->isSatisfiedBy($person)) {
    echo 'Woohoo!';
} else {
    echo 'Doh!';
}

The library implements AND, OR and NOT nodes to compose specifications. The basic tests provided are: starts with, ends with, contains, equals, greater or equal to and lesser or equal to. From these building blocks, you should be able to create a wide range of custom specifications.

Where are they useful? As was shown in this article, specifications can be useful in validating objects. This is particularly useful for services that are passed objects from unknown sources, making sure valid input is received before any processing is done. They can also be used in a similar fashion to filter a stream of objects.

It might also be possible to use specifications to define queries to send to your data layer, though the practicality of this is up for debate. In any case, I hope you find this useful.

Download Specifications Library

A Service Locator for PHP5

php No Comments »

For my first article, I thought I’d share something I’ve been cooking up at my day job. My only hope is that someone, somewhere finds this useful.

Dependency injection is a great way to decouple components and make your application more flexible and testable. But for many web apps, a full-on dependency injection mechanism can add a lot of complexity and be more difficult to maintain than it is really worth. Another way to decouple components is to use a Service Locator. It is simpler than dependency injection and provides the same benefits. But there is a trade-off.

The main trade-off between the two schemes is that dependency injection, while being more complex, does not require the dependent object to hold a reference to the injector. It is completely ignorant of how its dependencies are filled. Using a service locator requires the dependent object to reference the locator to acquire its dependencies, and so is coupled to it. But, this is often a worthwhile trade-off.

The service locator presented here is essentially a generic Registry that makes sure the object it returns is of the correct type. The first thing you need to do to use the locator is tell it to bind an abstract class or interface to a concrete implementation. Let’s say we have a service called EmployeeService that fetches employee records from a database and is defined something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
interface iEmployeeService {
    public function GetAllEmployees();
    public function GetEmployeeById($id);
}
 
class EmployeeService implements iEmployeeService {
    public function GetAllEmployees() {
        // query all records from database
    }
 
    public function GetEmployeeById($id) {
        // query database by Id
    }
}

Now, let’s say we have two different clients for this service. One is local and runs within the same application as the service itself. For this client, we can bind iEmployeeService directly to EmployeeService in our client application.

1
Locator::Bind('iEmployeeService', 'EmployeeService');

And when the client needs to access the service, instead of instantiating it directly, we use the locator to retrieve the object. So instead of

1
$employeeService = new EmployeeService;

we write

1
$employeeService = Locator::GetInstance('iEmployeeService');

The locator looks up the iEmployeeService interface, creates an instance of the EmployeeService class that it is bound to and returns it to the client, who doesn’t care what the locator returns, as long as it implements iEmployeeService.

Now, we also have another client that is remote and communicates to our services through SOAP. We can then write a Proxy or Plugin class that implements the iEmployeeService interface but, instead of performing the action itself, sends a message to the remote service and returns the response.

1
2
3
4
5
6
7
8
9
class EmployeeServiceSOAPProxy implements iEmployeeService {
    public function GetAllEmployees() {
        // send SOAP request and return reply
    }
 
    public function GetEmployeeById($id) {
        // send SOAP request and return reply
    }
}

Our remote client code is the same as our local code, except the Locator binds iEmployeeService to a different class.

1
Locator::Bind('iEmployeeService', 'EmployeeServiceSOAPProxy');

And our client goes merrily along its way, not knowing the difference. Pretty simple, eh?

So what have we gained from all this? We have decoupled our client (aka Presentation Layer) from our services and that’s a Good Thing(TM). It means easier testing of our client because we can test it separately from the services it depends on. It also gives us greater flexibility in how our client and services interact: local, remote; to our client it doesn’t matter.

On the downside, we now have a reference to Locator everywhere in the client. But this one reference replaces many and if we decide to change the client application to use ShinyNewEmployeeService instead of plain old EmployeeService, there is a single place we must make that change. Sounds like a win to me.

Download Locator class