Domain Driven Design (DDD) Concepts in ZF2

Domain Driven Design (DDD) is a pattern used in programming. With DDD, you are able to model the program to best map to your problem domain.

For example, assume that you need to develop a web site intended for selling goods from a catalog to a site visitor. By applying the DDD pattern, you will have the User entity that has some properties (username, password, etc.) and behaviors (it can log in and buying some item). Additionally, you will have an Item entity which is stored in a Catalog repository, the Order entity which represents user’s order. For international web sites, you might also need the CurrencyConverter service which will convert MoneyAmount value objects to the local currency of the User.

By having these entities, value objects, services and repositories, you will better understand the mapping between your business domain and its model implemented in the web site’s code.

DDD and Zend Framework 2

For me, Domain Driven Design is still one of the most obscure things related to development with Zend Framework 2. There is still not much good tutorials on this topic. In this post, I want to summarize my knowledge about DDD.

ZF2 uses the Model-View-Controller pattern. Based on that pattern, all the code the site consists of, can be divided into three group:

  • Controllers – responsible for getting user input from GET and POST variables and pass it to model layer;
  • Models – responsible for processing the input data based on site-specific business logic algorithms and produce some output data;
  • Views – responsible for generating the HTML code based on the output data returned by models.

In Zend Framework 2, by convention, you will have model layer further splitted into entities (classes mapped on database tables), repositories (classes used to retrieve entities), value objects (model classes not having identity), services (classes responsible for business logics). Additionally, you will have forms (classes responsible for collecting user input), view helpers (reusable plugin classes intended for rendering stuff) and others.

DDD Resources

For a beginner Zend Framework 2 developer, I would recommend the following two resources:

A short intro to Domain Driven Design can be found in this PDF by InfoQ: Domain Driven Design Quickly

Recently, I’ve watched the webinar called An introduction to Domain Driven Design with ZF2 (you will need to log into your Zend account to watch the webinar).

ZF2 Model Types

In Zend Framework 2, there is no single Model directory for storing the model classes. Instead, by convention, models are further subdivided into the following types, and each type is stored in its own subdirectory (see table below):

Model Type Directory
Entities APP_DIR/module/Application/src/Application/Entity
Value Objects APP_DIR/module/Application/src/Application/ValueObject
Services APP_DIR/module/Application/src/Application/Service
Repositories APP_DIR/module/Application/src/Application/Repository
Factories APP_DIR/module/Application/src/Application/Factory

Separation of models into different types makes it easier to design your business logic domain. This is also called the “Domain Driven Design” (or shortly, DDD). The person who proposed DDD was Martin Fowler in his famous book called Patterns of Enterprise Application Architecture.

Entities

Entities always have some identifier property, so you can uniquely identify the object. For example, a User entity always has a unique login property, and you can identify the user by that attribute. You can change some other attributes of the entity, like firstName, or address, but its identifier never changes. Entity models are usually stored in a database, in a file system or in any other storage.

Below, you can find an example a User entity, which represents a site visitor:

// The User entity represents a site visitor
class User {

  // Properties
  private $login;     // e.g. "admin"
  private $title;     // e.g. "Mr."
  private $firstName; // e.g. "John"
  private $lastName;  // e.g. "Doe"
  private $country;   // e.g. "USA"
  private $city;      // e.g. "Paris"
  private $zipCode;   // e.g. "10543"
  private $address;   // e.g. "Jackson rd."
    
  // Behaviors    
  public getLogin() {
    return $this->login;
  }
        
  public setLogin($login) {
    $this->login = $login;
  }
    
  //...
}

In lines 5-10, we define User model’s properties. The best practice is to
define the properties using the private access type, and make
them available to the caller through getter and setter public methods
(like getLogin() and setLogin(), etc).

Model’s behavior methods are not limited by getters and setters.
You can create other methods which manipulate with model’s data.
For example, you can define the getFullName() convenience method,
which would return the user’s full name, like “Mr. John Doe”.

Value Objects

Value objects are a kind of model for which the identity is not as important as for entities. A value object is usually a small class identified by all of its attributes. It does not have an identifier attribute. Value objects typically have getter methods, but do not have setters (value objects are immutable).

For example, a model wrapping a money amount can be treated as a value object:

class MoneyAmount {
  
  // Properties
  private $currency;
  private $amount;
  
  // Constructor
  public function __construct($amount, $currency='USD') {
    $this->amount = $amount;
    $this->currency = $currency;
  }
  
  // Gets the currency code  
  public function getCurrency() {
    return $this->currency;  
  }
  
  // Gets the money amount
  public function getAmount() {
    return $this->amount;
  }  
  
  // Converts the money amount into new currency
  public static function convert($newCurrency) {
    // Use currency exchange rates algorithm to determine the
    // new amount.
    if($this->currency=='USD' && $newCurrency=='EUR') {
      $newAmount = 1.1*$this->amount;
      return new MoneyAmount($newAmount, $newCurrency); 
    } else {
      throw new Exception('Unknown currency code');
    }
  }
}

In lines 4-5 we define two properties: currency and amount. The model has no identifier property, instead it is identified by all properties as a whole: if you change either the currency or amount, you would have a different money amount object.

In lines 8-10 we define the constructor method, which initializes the properties. In lines 14-21, we define getter methods for model’s properties. Note that we do not have setter methods (the model is immutable).

In lines 24-33 we have the static method convert(), which is designed to convert money amount to another currency using some simple currency conversion algorithm. Instead of modifying the money amount properties, it constructs and returns a new MoneyAmount object.

The real life is much more difficult than we described above, and you should be “flexible” enough to adapt your entities and value objects to real conditions. In some situations you will have a value object which is “mutable” (have setter methods), and sometimes, you will have only getter methods for some of entity properties. Do not dwell on the idealistic recommendations provided by others, instead adapt your models as your intuition advices to you.

Services

Service models usually encapsulate some business logic functionality. Services typically do not have state (internal properties), instead they manipulate other entity models and value objects. Services usually have easily recognizable names ending with “er” suffix, like FileUploaderService or UserManagerService.

Below, an example of MailerService service is presented. It has the sendMail()
method which takes an EmailMessage value object and sends an E-mail message using standard PHP mail() function:

// The Email message value object
class EmailMessage {  
  private $recipient;
  private $subject;
  private $text;  
  
  // Constructor
  public function __construct($recipient, $subject, $text) {
    $this->recipient = $recipient;
    $this->subject = $subject;
    $this->text = $text;
  }
  
  // Getters
  public function getRecipient() {
    return $this->recipient;
  }
  
  public function getSubject() {
    return $this->subject;
  }
  
  public function getText() {
    return $this->text;
  }
}

// The Mailer service, which can send messages by E-mail
class MailerService {
  
  public function sendMail($message) {
    // Use PHP mail() function to send an E-mail
    if(!mail($message->getRecipient(), $message->getSubject(), 
             $message()->getText())) 
    {
      // Error sending message
      return false
    }
    
    return true;
  }
}

Factories

Factories are usually being designed to instantiate other models. In the simplest cases you can create an instance of a class without any factory, just by using the new operator, but sometimes class creation logic might be very complex, and you encapsulate it inside of a factory class. Factory classes typically have names ending with Factory suffix, like ResourceFactory, FileFactory, etc.

For example, let’s consider the case when you use a CAPTCHA image in a web form. The image is a type of challenge-response test used to determine whether the user is a human or a robot.

There may be different CAPTCHA types: simple image captcha, reCAPTCHA and so on. Let’s create a fictitious CaptchaFactory class, whose only goal is to create different CAPTCHA images based on the $type argument you pass to its createCaptcha() method.

// The CaptchaFactory class is used to create CAPTCHA
// image for a web form.
class CaptchaFactory {

  // Creates a CAPTCHA object based on type parameter
  public static function createCaptcha($type) {
    if($type=='Image')
      return new ImageCaptcha();
    else if($type=='ReCaptcha')
      return new ReCaptcha();
    else
      throw new Exception('Unknown captcha type');
  }
}

Repositories

Repositories are specific models responsible for storing and retrieving entities.
For example, a UserRepository may represent a database table and provide methods
for retrieving User entities. You typically use repositories when storing entities
in a database. With repositories, you can encapsulate SQL query logic in the
single place and easily maintain and test it.

Note: This post is an excerpt of my Using Zend Framework 2 e-Book.

Advertisements

I am a software developer currently living in Tomsk, Russia. I received a PhD degree in Computer Science from Tomsk Polytechnic University in 2010. I have been professionally developing C/C++ and PHP software since 2005. I like contributing to open-source and writing programming articles for popular web resources, like CodeProject. Besides writing, I love skiing and watching Formula-1.

Tagged with: , , ,
Posted in Zend Framework 2
3 comments on “Domain Driven Design (DDD) Concepts in ZF2
  1. Yukiron says:

    This is very good article for developers who want to start building an application with ZF2. I would like to ask a question:

    Lets say i have a MoneyAmount ValueObject and i want to read exchange rate from persistency or caching layer. (In the examples above, exchange rate 1.1 and its hardcoded).

    The question is which class(es) responsible for fetching that rate from database or caching layer and what is the proper way to tell our MoneyAmount class “-hey this is the current exchange rate. Consider using this rate when converting an amount” If i add getRate() like method to MoneyAmount class it will be tightly-coupled to persistency or caching layer.

    • Hello Yukiron,

      Thanks for the real-life question. Actually, instead of keeping the `convert($newCurrency)` method in the `MoneyAmount` value object class, I would implement the `CurrencyConverter` service, which would connect to database (for database management, I would use Doctrine library) and retrieve the current exchange rate. Then I would create the `convertCurrency($moneyAmount, $newCurrency)` method in that service class, which would take two arguments: the money amount to convert, and the destination currency ID. That method would create an instance of another `MoneyAmount` value object, set its properties, and return it.

      Oleg

  2. theotherstupiedguy says:

    Eric Evans in 2003 introduced domain driven design in his book tackling complexty in the heart of software, martin is just a big fan 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow ValuableThing on WordPress.com
%d bloggers like this: