Chinaunix首页 | 论坛 | 博客
  • 博客访问: 574860
  • 博文数量: 207
  • 博客积分: 10128
  • 博客等级: 上将
  • 技术积分: 2440
  • 用 户 组: 普通用户
  • 注册时间: 2004-10-10 21:40
文章分类

全部博文(207)

文章存档

2009年(200)

2008年(7)

我的朋友

分类: 系统运维

2009-04-06 16:51:14

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.

阅读(603) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~