当前位置:  开发笔记 > 编程语言 > 正文

了解Domain对象+ Data mapper模式?

如何解决《了解Domain对象+Datamapper模式?》经验,为你挑选了2个好方法。

我过去总是使用各种ORM,并将我的所有逻辑放在我的模型中,无论它的性质如何 - SQL,MongoDB查询甚至获取远程JSON对象.但是,当有必要确保松散耦合以实现高水平的可测试性时,很快就会出现这种方法的问题.

今天我读到了将模型分成两部分,Domain objects&Data mappers.
如果我完全理解它,Domain objects完全不知道所使用的存储,而是存在以处理业务逻辑.Data mappers另一方面,负责将数据集存储Domain objects到设定数据存储器中.

但是,我觉得在现实世界的例子中,如何使用DomainObjects和DataMappers在线找到一个好的,易于理解的例子有点困难.

这个(下面显示的代码)是否是在我的代码中使用DomainObjects和DataMappers来存储用户的合适方式,还是我在脑子里弄错了?

$user = new User_DO;
$userSave = new User_DM;
$userSave->store( $user->add(array('name' => 'John Doe')) );

class User_DO {

    function add($array) {
        if(!isset($array['name'])) {
            throw new Exception("Name must be set");
        }

        return $array;

    }

}

class User_DM {

    function store($array) {
        MyDatabase::execute("INSERT INTO...");
    }

}

Lars.. 25

这背后的想法是拥有一个标准对象,它代表现实生活中的当前状态,换句话说,代表领域中的当前状态.此域模型通常是没有逻辑的数据集合.

class person_DO {
    public $id;
    public $firstname;
    public $lastname;
    public $addresses;
}

加载此域模型(域对象)的实例和持久性是通过数据映射器处理的- 例如,上述人员的地址可能通过1:n关系位于另一个表中,如下所示:

TABLE person {
    id        INTEGER PRIMARY KEY,
    firstname VARCHAR(32),
    lastname  VARCHAR(32)
}

TABLE addresses {
    id INTEGER PRIMARY KEY,
    person_id  INTEGER FOREIGN KEY ON person.id, --Reference on person-row
    street     VARCHAR(64),
    ...
}

person_DO不需要知道这一点,但数据映射器确实如此,因为它必须在加载期间聚合数据并在持久化期间分离:

class person_DM {
    /**
     * @param  [integer] $id
     * @return [person_DO] an instance of a person or null, if no person
     *                     with that id was found.
     */
    public function findById ($id) {...}

    /**
     * @return [array of person_DO]
     */
    public function fetchAll() {...}

    /**
     * persists a person object
     * @param [person_DO] an instance of a person
     */
    public function saveOrUpdate(person_DO $person) {...}
}

为了更加分离不同的部分,DataMappers通常使用DbTable Gateway或类似的模式来允许使用不同的数据库或类似的操作.这样,我可以拥有几个具有相同模式的数据库,但是例如在不同的组织中构建具有相同代码的数据仓库,只有不同的数据库对象.

作为一个实际的例子,我建议查看Zend框架的快速入门教程,它完全按照我刚才解释的那样做.



1> Lars..:

这背后的想法是拥有一个标准对象,它代表现实生活中的当前状态,换句话说,代表领域中的当前状态.此域模型通常是没有逻辑的数据集合.

class person_DO {
    public $id;
    public $firstname;
    public $lastname;
    public $addresses;
}

加载此域模型(域对象)的实例和持久性是通过数据映射器处理的- 例如,上述人员的地址可能通过1:n关系位于另一个表中,如下所示:

TABLE person {
    id        INTEGER PRIMARY KEY,
    firstname VARCHAR(32),
    lastname  VARCHAR(32)
}

TABLE addresses {
    id INTEGER PRIMARY KEY,
    person_id  INTEGER FOREIGN KEY ON person.id, --Reference on person-row
    street     VARCHAR(64),
    ...
}

person_DO不需要知道这一点,但数据映射器确实如此,因为它必须在加载期间聚合数据并在持久化期间分离:

class person_DM {
    /**
     * @param  [integer] $id
     * @return [person_DO] an instance of a person or null, if no person
     *                     with that id was found.
     */
    public function findById ($id) {...}

    /**
     * @return [array of person_DO]
     */
    public function fetchAll() {...}

    /**
     * persists a person object
     * @param [person_DO] an instance of a person
     */
    public function saveOrUpdate(person_DO $person) {...}
}

为了更加分离不同的部分,DataMappers通常使用DbTable Gateway或类似的模式来允许使用不同的数据库或类似的操作.这样,我可以拥有几个具有相同模式的数据库,但是例如在不同的组织中构建具有相同代码的数据仓库,只有不同的数据库对象.

作为一个实际的例子,我建议查看Zend框架的快速入门教程,它完全按照我刚才解释的那样做.


"这个域模型通常是没有逻辑的数据集合." 这根本不准确.那是一个贫穷的模型和贫穷的穷人,你的域逻辑应该在你的域对象中,这是简单的封装.
@Andrew,@ AgmLauncher,Lars在这里用`person_DO`描述的是域*实体*和域*逻辑*之间的分离,这是一个非常常见的事情(但当然,不是必需的).尽量不要挂断条款,而是想法.

2> Marijn Huize..:

大概的方式,是的.虽然我强烈建议不要重新发明轮子并使用像Doctrine 2.x那样实现这种模式的复杂ORM .您可以查看他们的文档(第8章:使用对象)来对接口进行采样.

推荐阅读
有风吹过best
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有