Federico Cargnelutti

Simple is better than complex. Complex is better than complicated. | @fedecarg

Archive for the ‘Agile Development’ Category

Domain-Driven Design with Zend Framework

with 21 comments

Part 1: Domain-Driven Design and MVC Architectures
Part 2: Domain-Driven Design: Data Access Strategies
Part 3: Domain-Driven Design: The Repository

Some of the Domain-driven design concepts explained in my previous posts are applied in this sample application. I’m also going to use the Zend Framework infrastructure to speed up some development tasks.

Directory Structure

app/     -> Application and UI Layers
domain/  -> Domain Layer
lib/     -> Infrastructure Layer

Application and UI Layers

app/
    controllers/
        UserController.php
    views/
        layouts/
        scripts/

Domain Layer

This layer should be well separated from the other layers and it should have few dependencies on the framework(s) you are using. I’m going to group all the classes and interfaces under the namespace “Project” and add it to my include path:

domain/
    Project/
        Dao/
            Db/
                IUser.php
                IUserProfile.php
                User.php
                UserProfile.php
        Model/
            User/
                IRepository.php
                Repository.php
            User.php
            UserProfile.php
            Users.php

Infrastructure Layer

This layer acts as a supporting library for all the other layers:

lib/
    Zend/
        ...
    Zf/
        Persistence/
            Db/
                Adapter.php
                Exception.php
                Replicated.php
        Domain/
            Collection.php
            Entity.php
            Exception.php
            Repository.php

User Entity

The User and UserProfile objects have a one-to-one relationship and form an Aggregate. An Aggregate is as a collection of related objects that have references between each other. Within an Aggregate there’s always an Aggregate Root (parent Entity), in this case User:

class Project_Model_User extends Zf_Domain_Entity
{
    /* SELECT id, name FROM user WHERE id = ? */
    private $properties = array(
        'id'      => null,
        'name'    => null
    );

    /* @var Project_Model_UserProfile */
    private $profile;

    public function __construct($array)
    {
        $this->populate($array);
    }
}

abstract class Zf_Domain_Entity
{
    private $properties = array();

    public function __call($method, $args) {}
    public function __set($key, $value) {}
    public function __get($key) {}
    public function __isset($key) {}
    public function __unset($key) {}
    public function populate($values) {}
    public function hasDependency($property) {}
    public function setDependency($property, $object) {}
    public function getDependency($property) {}
}

Usage:

$array = array('id'=>1, 'name'=>'Federico');
$user = new Project_Model_User($array);
$user->setProfile($profile);

echo $user->getId();   // Outputs 1
echo $user->getName(); // Outputs Federico

Users Collection

A collection is simply an object that groups multiple elements into a single unit.

class Project_Model_Users extends Zf_Domain_Collection
{
    public function __construct($users)
    {
        foreach ($users as $user) {
            if (!($user instanceof Project_Model_User)) {
                throw new Zf_Domain_Exception(...);
            }
            $this->append($user);
        }
    }
}

abstract class Zf_Domain_Collection implements Countable, Iterator
{
    ...
}

User DAO

The UserDAO class allows data access mechanisms to change independently of the code that uses the data:

class Project_Dao_Db_User extends Zf_Persistence_Db_Adapter
{
    public function find($id)
    {
        $db = $this->getAdapter();
        $query = $db->select();
        $query->from('user');
        $query->where('id = ?', $id);
        $result = $db->fetchRow($query);

        return $result;
    }

    public function findAll()
    {
        ...
        return $resultSet;
    }
}

User Repository

A Repository is basically a collection of Aggregate Roots. Collections are used to store, retrieve and manipulate Entities and Value objects, however, object management is beyond the scope of this post.

The UserRepository object injects dependencies on demand, making the instantiation process inexpensive. A caller method is responsible for dynamically creating the setter and getter methods. You can easily mock objects by passing a custom config array via the constructor.

class Project_Model_User_Repository extends Zf_Domain_Repository
{
    /* @var Project_Dao_Db_User */
    private $userDao;

    /* @var Project_Dao_Db_UserProfile */
    private $userProfileDao;

    /* @var array IoC Spec */
    private $inject = array(
        'userDao'        => 'Project_Dao_Db_User',
        'userProfileDao' => 'Project_Dao_Db_UserProfile'
    );

    public function getUserById($id)
    {
        $row = $this->getUserDao()->find($id);
        $user = new Project_Model_User($row);

        $row = $this->getUserProfileDao()->findByUserId($id);
        $profile = new Project_Model_Profile($row);
        $user->setProfile($profile);

        return $user;
    }

    public function getUsers()
    {
        $users = array();
        $rows = $this->getUserDao()->findAll();
        foreach ($rows as $row) {
            $users[] = new Project_Model_User($row);
        }

        return new Project_Model_Users($users);
    }
}

abstract class Zf_Domain_Repository
{
    ...
    public function __call($method, $arguments)
    {
    	$property = lcfirst(substr($method, 3));
        if (!property_exists($property)) {
            throw new Zf_Domain_Exception(...);
        }
        if (null === $this->$property
            && array_key_exists($property, $this->inject)) {
        	$this->$property = new $this->inject[$property];
        }
        return $this->$property;
    }
    ...
}

Usage:

$repo = new Project_Model_User_Repository();
$user = $repo->getUserById(1);
$profile = $user->getProfile();
$users = $repo->getUsers();

Links

If you’re interested in learning more about Domain-driven design, I recommend the following articles:

Written by Federico

March 22, 2009 at 2:06 pm

Domain-Driven Design: The Repository

with 18 comments

Part 2: Domain-Driven Design: Data Access Strategies

The Ubiquitous Language

The ubiquitous language is the foundation of Domain-driven design. The concept is simple, developers and domain experts share a common language that both understand. This language is set in business terminology, not technical terminology. This ubiquitous language allows the technical team become part of the business.

The Repository

Repositories play an important part in DDD, they speak the language of the domain and act as mediators between the domain and data mapping layers. They provide a common language to all team members by translating technical terminology into business terminology.

In a nutshell, a Repository:

  • Is not a data access layer
  • Provides a higher level of data manipulation
  • Is persistence ignorance
  • Is a collection of aggregate roots
  • Offers a mechanism to manage entities

Injecting DAO’s

In DDD, you inject Repositories, not DAO’s in domain entities. In the absence of an ORM framework, the DAO handles the impedance mismatch that a relational database has with object-oriented techniques. For example, imagine you have an entity named User that needs to access the database to retrieve the User details:

class User
{
    // DAO needs to be injected
    private $_dao;
    private $_data;

    public function setDao(UserDaoInterface $dao) {}
    public function getDao() {}

    public function setData($data) {}
    public function getData()
    {
        if (null === $this->_data) {
            $data = $this->getDao()->find($id);
            $this->setData($data);
        }
        return $this->_data;
    }
}

The User DAO class will look something like this:

interface UserDaoInterface
{
    public function find($id);
}

class UserDaoDb implements UserDaoInterface
{
    // Db needs to be injected
    private $_db;

    public function setDb(DbInterface $db) {}
    public function getDb() {}

    public function find($id)
    {
        $db = $this->getDb();

        $query = $db->select();
        $query->from('user');
        $query->where('id = ?', $id);

        return $db->fetchRow($query);
    }
}

$userDao = new UserDaoDb();
$userDao->setDb($db);

$user = new User();
$user->setDao($userDao);
$data = $user->getData();

Is there an easier way to create entities and inject dependencies? The process of creating an entity is complex, because an entity always has relationship with other objects in your domain model. When creating an entity, we have to initialize its relationships as well. Therefore, it’s a good practice to delegate this task to another object.

But, what about separation of concerns? DAO’s are related to persistence, and persistence is infrastructure, not domain. The main problem with the example above is that we have lots of different concerns polluting the domain. According to DDD, an object should be distilled until nothing remains that does not relate to its meaning or support its role in interactions. And that’s exactly the problem the Repository pattern tries to solve.

Injecting Repositories

Lets create a UserRepository class to isolate the domain object from details of the UserDaoDb class:

class User
{
    // Repository needs to be injected
    private $_repository;
    private $_data;

    public function setRepository(UserRepositoryInterface $repo) {}
    public function getRepository() {}

    public function setData($data) {}
    public function getData()
    {
        if (null === $this->_data) {
            $data = $this->getRepository()->getUserById($id);
            $this->setData($data);
        }
        return $this->_data;
    }
}

It’s the responsibility of the UserRepository to work with all necessary DAO’s and provide all data access services to the domain model in the language which the domain understands.

class UserRepositoryInterface
{
    public function getUserById($id);
}

class UserRepository implements UserRepositoryInterface
{
    // DAO needs to be injected
    private $_userDao;

    public function setUserDao(UserDaoInterface $userDao) {}
    public function getUserDao() {}

    public function getUserById($id)
    {
        return $this->getUserDao()->find($id);
    }
}

$userDao = new UserDaoDb();
$userDao->setDb($db);

$userRepo = new UserRepository();
$userRepo->setUserDao($userDao);

$user = new User();
$user->setRepository($userRepo);
$data = $user->getData();

The main difference between the Repository and the DAO is that the DAO is at a lower level of abstraction and doesn’t speak the ubiquitous language of the domain.

So, what’s next?

We’ve seen how to write a persistence-ignorant domain model. Next, I’ll explain how to automate the creation and injection of dependencies.

Part 4: Zend Framework Domain-Driven Design

Written by Federico

March 15, 2009 at 3:20 am

Domain-Driven Design: Data Access Strategies

with 11 comments

Part 1: Domain-Driven Design and MVC Architectures

The Domain Model

Here are some of the features a Domain-driven design framework should support:

  • A domain model that is independent and decoupled from the application.
  • A reusable library that can be used in many different domain-specific applications.
  • Dependency Injection in order to inject Repositories and Services into Domain Objects.
  • Integration with unit testing frameworks, such as PHPUnit.
  • Good integration with other frameworks, such as Zend, Symfony, Doctrine, etc.

The Zend Framework, for example, is part of the infrastructure layer and acts as a supporting library for all the other layers. However, the domain layer should be well isolated from the other layers of the application and should not be dependent on the framework you are using.

Data Access Strategies

When accessing data from a data source, you have to decide how your application will communicate with a data source. Each data access strategy has its own advantages and disadvantages. Here are some design patterns that support DDD:

Generic DAO’s

Data Access Objects (DAO’s) and Repositories play an important role in DDD. The goal of a DAO is to abstract and encapsulate all access to the data and provide an interface. The DAO always connects, reads and saves data to a data source. From the applications point of view, it makes no difference when it accesses a database, XML file or Web service:

$user = new UserDbDao();
$row = $user->findUserById(456);
echo $row->name;

$user = new UserXmlDao();
$row = $user->findUserById(456);
echo $row->name;

Table Data Gateway

An object that acts as a Gateway to a database table. One instance handles all the rows in the table. The Zend_Db_Table solution is an implementation of the Table Data Gateway pattern:

$user = new User();
$rows = $user->find(456);
$row = $rows->current();
echo $row->name;

More info: Table Data Gateway

Row Data Gateway

An object that acts as a Gateway to a single record in a data source. There is one instance per row. Zend_Db_Table_Row is an implementation of the Row Data Gateway pattern:

$user = new User();
$row = $user->fetchRow($user->select()->where('user_id = ?', 1));
echo $row->name;

More info: Row Data Gateway

Active Record

An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data. The Mad_Model component is an  ORM layer that follows the Active Record pattern where tables map to classes, rows map to objects, and columns to object attributes:

$user = new User();
$userFinder = new UserFinder();
$row = $userFinder->find(456);

More info: Active Record

Data Mapper

A layer of Mappers that moves data between objects and a database while keeping them independent of each other and the mapper itself:

$user = new User();
$userMapper = new UserMapper();
$row = $userMapper->findByEmail($email);

More info: Data Mapper

Data Transfer Objects

A Data Transfer Object (DTO) in Domain-driven design is not the same as a Value Object. A DTO is often used in combination with a DAO to encapsulate data. It allows you to reduce communication effort when dealing with a lot of small data entities. For example:

class UserData
{
    public function setId($id) {}
    public function getId() {}
    public function setFirstName($firstName) {}
    public function getFirstName() {}
    public function setLastName($lastName) {}
    public function getLastName() {}
}

$user = new UserData();
$user->setFirstName('Jim');
$user->setLastName('Morrison');

$userDao = new UserDbDao();
$userDao->insert($user);

A DTO is a simple container for a set of aggregated data. It should contain no business logic and limit its behaviour to activities such as internal consistency checking and basic validation. Be careful not to make the DTO depend on any new classes as a result of implementing these methods.

Part 3: Domain-Driven Design: The Repository

Written by Federico

March 12, 2009 at 11:33 pm

Domain-Driven Design and MVC Architectures

with 12 comments

According to Eric Evans, Domain-driven design (DDD) is not a technology or a methodology. It’s a different way of thinking about how to organize your applications and structure your code. This way of thinking complements very well the popular MVC architecture. The domain model provides a structural view of the system. Most of the time, applications don’t change, what changes is the domain. MVC, however, doesn’t really tell you how your model should be structured. That’s why some frameworks don’t force you to use a specific model structure, instead, they let your model evolve as your knowledge and expertise grows.

Domain-driven design separates the model layer “M” of MVC into an application, domain and infrastructure layer. The infrastructure layer is used to retrieve and store data. The domain layer is where the business knowledge or expertise is. The application layer is responsible for coordinating the infrastructure and domain layers to make a useful application. Typically, it would use the infrastructure to obtain the data, consult the domain to see what should be done, and then use the infrastructure again to achieve the results. Srini Penchikala explains this in more detail here: “Domain Driven Design and Development In Practice“.

Object-oriented programming is the most important element in the domain implementation. Domain objects are designed using classes and interfaces, and take advantage of OOP concepts like inheritance, encapsulation, and polymorphism. Most of the domain elements are true objects with both State (attributes) and Behaviour (methods or operations that act on the state). Entities and Value Objects in DDD are classic examples of OOP concepts since they have both state and behaviour.

Terminology used by Domain-driven design

  • Entity: An object which has a distinct identity. For example, a User entity has a distinct identity with an ID.
  • Value Object: An object which has no distinct identity, like numbers and dates. For example, if two Users have the same date of birth, you can have multiple copies of an object that represents the date 16 Jan 1982.
  • Factory: Used to create Entities. For example, you can use a Factory to create a Profile entity from a User entity.
  • Repository: Used to store, retrieve and delete domain objects from different storage implementations. For example, you can use a Repository to store the Profile your Factory created.
  • Service: When an operation does not conceptually belong to any object.

The purpose of this post was to provide a brief introduction to Domain-driven design.

Part 2: Domain-Driven Design: Data Access Strategies

Links

If you’re interested in learning more about Domain-driven design or Model-driven design, I recommend the following articles:

Written by Federico

March 11, 2009 at 12:14 am

10 reasons to switch from CruiseControl to Hudson

with 2 comments

Ten things no one ever told you about Hudson:

  1. It’s extremely easy to install (unzip the file and that’s it)
  2. It can be configured entirely from its friendly Web UI (no XML required)
  3. It has an attractive dashboard with colourful and meaningful icons
  4. It’s extremely flexible
  5. It can be extended via plug-ins
  6. It offers a much better UI than CruiseControl
  7. It can execute Phing, Ant, Gant, NAnt and Maven build scripts
  8. It gives you clean readable URLs for most of its pages
  9. It has RSS, e-mail and IM integration
  10. It can distribute build/test loads to multiple computers

This tutorial guides you step-by-step through the fundamental concepts of Continuous Integration and Hudson. When you are done with this one-hour tutorial, you will understand the benefits of Continuous Integration as well as how to set up your environment.

Links

Written by Federico

March 5, 2009 at 12:43 am

Four Great InfoQ Presentations

with one comment

Hope you like these recommendations and if you know of any other good tech-related video, then please let me know.

1. Developing Expertise: Herding Racehorses, Racing Sheep

One of my favourites. In this presentation Dave Thomas (The Pragmatic Programmer) talks about expanding people’s expertise in their domains of interest by not treating them uniformly as they had the same amount of knowledge and level of experience.

Developing Expertise

2. Real World Web Services

Another good presentation. In this one Scott Davis provides a pragmatic, down-to-earth introduction to Web services as used in the real world by public sites, including SOAP-based and REST examples.

Real World Web Services

3. CouchDB and me

This presentation is different, and that’s why I like it so much. Damien Katz shares his experiences and reminds people how difficult but at the same time gratifying is to be an open source developer. He talks about the history of CouchDB development from a very personal point of view. His inspirations for CouchDB and why he decided to move my wife and kids to a cheaper place and live off savings to build this thing.

CouchDB and me

4. Yahoo! Communities Architectures

In this presentation, Ian Flint tries to explain the infrastructure and architecture employed by Yahoo! to keep going a multitude of servers running of different platforms and offering different services. Very interesting!

Yahoo! Communities Architectures

Written by Federico

February 6, 2009 at 12:02 am

The Importance of Branching Models

with 2 comments

Among the branching models used in software configuration management, the branch-by-purpose model offers better support for parallel development efforts and improved control of both planned and emergency software releases. If you want to improve software quality, you must first understand your software. What are its pieces? How are they organized and related to one another? If you do not understand your code base, your odds of updating it without breaking something are poor.

The Importance of Branching Models (PDF)

Links

High-level Best Practices in Software Configuration Management

Written by Federico

January 7, 2009 at 4:03 pm

Scrum Backlog Templates

with 2 comments

Here are two useful backlog templates provided by Agile Software Development. Both of them are in Excel format (XLS). Check them out:

Written by Federico

November 18, 2008 at 10:20 pm

How to kill an idea, or help it grow

with 4 comments

It is far easier to kill an idea than to encourage it and turn it into a useful solution. Be on a constant watchout for putting down an idea too early without understanding the positive reasons for it being suggested. Hopefully you will see that there are many ways in which you can be constructive.

To kill an idea, say:

  • It’s not part of your job
  • That’s not what we do here
  • Costs too much
  • Against the company policy
  • It’s not budgeted, maybe next year
  • Let the other department handle that
  • It is not our problem
  • Why would you do something like that?
  • We have been doing it another way for a long time and it works fine
  • If it’s so good, why hasn’t someone suggested it already?
  • Has anyone else tried it successfully?
  • We have tried that before and it didn’t work
  • Is anyone crazy enough to try that?
  • We’re already doing that

To help an idea, say:

  • Yes, and…
  • Great, let’s try it
  • How can we make time to see if it will work?
  • What resources would we need to do it? Tell me more
  • How can we make it work?
  • What are the advantages?
  • How can we remove the dis-advantages?
  • What can I do to help this happen?
  • I like it
  • That sounds interesting, tell me more
  • How can we convince everyone else?

Written by Federico

November 6, 2008 at 9:28 pm

Leading a Software Development Team

with 4 comments

36 steps to success as technical lead

  1. Define early on what success means for you, the team and the business.
  2. Believe in the project: idea, architecture, time, team.
  3. Understand the domain, the business requirements and the technical challenges.
  4. Know your team: strengths, weaknesses, ambitions and personalities.
  5. Have a plan as a result of a planning activity.
  6. Be part in the design of everything.
  7. Get your hands dirty and code.
  8. Act as a communication proxy for your team.
  9. Make sure everybody understands the big picture: their work has implications.
  10. Fight for architecture and design consistency.

Read more

How not to lead geeks

  1. Downplay training.
  2. Give no recognition.
  3. Plan too much overtime.
  4. Use management-speak.
  5. Try to be smarter than the geeks.
  6. Act inconsistently.
  7. Ignore the geeks.
  8. Make decisions without consulting them.
  9. Don’t give them tools.
  10. Forget that geeks are creative workers.

Read more

Nine things developers want more than money

  1. Being set up to succeed.
  2. Having excellent management.
  3. Learning new things.
  4. Exercising creativity and solving the right kind of problems.
  5. Having a voice.
  6. Being recognized for hard work.
  7. Building something that matters.
  8. Building software without an act of congress.
  9. Having few legacy constraints.

Read more

Top 10 ways to demotivate your programming team

  1. Set up impossible deadlines.
  2. Let them work overtime.
  3. Don’t allow breaks.
  4. Place a ban on laughing.
  5. Break the coffee machine.
  6. Don’t shield them from the dirty daily business.
  7. Don’t challenge them.
  8. Underpay them.
  9. Bribe them.
  10. Infiltrate a team member who is demotivated anyway.

Read more

Don’t bring me solutions, bring me problems

(Don’t tell me how you want it to work, tell me what you want it to do)

  1. Where all think alike, no one thinks very much.
  2. Suggesting solutions kills creativity.
  3. Don’t bring me solutions, bring me problems.

Read more

Classic mistakes enumerated

  1. Undermined motivation.
  2. Weak personnel.
  3. Uncontrolled problem employees.
  4. Heroics.
  5. Adding people to a late project.
  6. Noisy, crowded offices.
  7. Friction between developers and customers.
  8. Unrealistic expectations.
  9. Lack of effective project sponsorship.
  10. Lack of stakeholder buy-in.
  11. Lack of user input.
  12. Politics placed over substance.
  13. Wishful thinking.

Read more

Written by Federico

September 21, 2008 at 11:23 pm