DDD - 实体创建和验证责任

时间:2012-02-06 14:41:51

标签: php domain-driven-design

我最近几天对DDD(领域驱动设计)感兴趣,但我无法弄清楚谁创建和验证实体的责任。我会打破这些问题以涵盖不同的情景。

  1. 常规实体(可能带有价值对象)。举个例子,我们可以选择一个由Email识别的用户。我有一个UserFactory接收一个数据数组(可能来自表单POST),并返回一个新的UserEntity。工厂应该验证数据的完整性(例如:作为电子邮件提供的字符串是真实的电子邮件,密码字段1和字段2中的密码匹配等)?工厂是否应该验证不存在此类用户(我们不想使用相同的电子邮件注册两个用户)?如果是,它应该是我自己还是使用UserRepository?

  2. 汇总实体。让我们假设我们有一个Post实体和Comments实体。我希望在帖子12中发表所有评论,所以我做了类似

    的事情

    $ post = $ postRepository-> getById(12);

  3. 如何实施getById?像这样:

    public function getById($id) {
        $postData = $this->magicFetchFromDB($id);
        $comments = (new CommentRepository())->getForPost(12);
        return new PostEntity($postData, $comments);
    }
    

    也许是负责懒惰创建评论的帖子,如:

    class PostEntity {
        public function getComments() {
            if(is_null($this->_comments)) $this->_comments = (new CommentRepository())->getForPost($this->_id);
            return $this->_comments;
        }
    }
    

    ? 我在这里很丢失,并且没有足够的信息提供PHP中的DDD示例,所以任何帮助都将不胜感激!

    非常感谢, skwee。

2 个答案:

答案 0 :(得分:4)

  • 工厂关心创建实体。我个人更喜欢在我的视图和模型层中进行验证。我会使用像jQuery的验证插件这样的库来在客户端进行一些必要的验证(比如检查必需字段是否有数据)。然后对模型进行“硬核”验证。    我这样做是通过使用所有实体扩展的简单BaseEntity抽象类,并且因为你问了一个例子,这里是:

    abstract class BaseEntity {
        public function isValid();
    }         
    
    class MyEntity extends BaseEntity {
         public function isValid() {
             //actual validation goes here
         }
     }
    

    您还可以使用带有一些基本验证方法的静态助手类:

    class ValidationHelper {
        public static function isValidPhonenumber($value) {
            //check valid phonenumber, using a regex maybe
        }
    
        public static function isAlphanumeric($value) {
            //check for letters and numbers only
        }
    }
    

    许多人反对静态方法,因为它们可以破坏单元测试,但在这种情况下,它们非常基本,并且没有外部依赖性,从而使它们“更安全”。

  • 在检查现有实体时,您可以通过在添加/更新之前查询数据库以查看实体是否已经存在,或者(我喜欢这样做)您可以添加对那些无法在数据库中重复的列的unique索引,然后将创建或更新查询包装在try-catch块中(如果两个用户具有相同的e,则查询将抛出唯一的约束违例例如,邮件)然后显示正确的错误消息

  • 关于你的最后一个问题,归结为一个偏好问题。如果您的数据库在1分钟内会获得一百万次点击,那么使用延迟加载可能会更好,以避免在需要之前获取不必要的数据。但是,如果您的数据库相对较小,您可以完全使用急切加载而不会牺牲太多性能。 同样,这是个人偏好的问题。

希望这种漫无边际的一些有道理,欢呼!

答案 1 :(得分:1)

最好和最简单的方法是使用Doctrine2。也许第一个小时会很难,但是一旦掌握了Doctrine2,所有这些关系和聚合都是小菜一碟。

您可以找到有关PHP&的大量信息。 http://giorgiosironi.blogspot.com/上的DDD或Doctrine2,或者只是通过Google搜索。

RE:验证 - 考虑单一责任原则,我们使用验证对象。验证可能很复杂,可能需要其他存储库或实体,因此最好将其与实际实体区分开来 - 验证的主题是为了避免创建膨胀对象。您可以使用访客或规范设计模式。

此处有很多关于这些主题的帖子 - 尝试使用上述关键字。