Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Domain driven design 域逻辑和按ID引用AR_Domain Driven Design_Aggregateroot - Fatal编程技术网

Domain driven design 域逻辑和按ID引用AR

Domain driven design 域逻辑和按ID引用AR,domain-driven-design,aggregateroot,Domain Driven Design,Aggregateroot,我正在尝试使用DDD为一个简单的应用程序建模 考虑以下简化代码,其中的想法是在父帖子被隐藏时隐藏注释: class Post { private $hidden; public function isHidden() { return $this->hidden; } } class Comment { private $post; private $hidden; public __construct(Post

我正在尝试使用DDD为一个简单的应用程序建模

考虑以下简化代码,其中的想法是在父帖子被隐藏时隐藏注释:

class Post {

    private $hidden;

    public function isHidden() {
        return $this->hidden;
    }

}

class Comment {
    private $post;

    private $hidden;

    public __construct(Post $post) {
        $this->post = $post;
    }

    public function isHidden() {
        if($this->hidden || $this->post->isHidden()){
            return true;
        }
    }

}
我将评论和帖子视为聚合根

在阅读了关于使用聚合根的Id而不是引用引用聚合根的内容后,我将Comments reference to Post更改为Post Id,并立即捕获了单元测试中的错误,因为这行代码:

$this->post->isHidden()

这种逻辑不应该在域层吗?这可能是我设计聚合的方式中的一个问题吗?

如果
Post
Comment
hidden
属性必须始终是强一致的,那么您可能需要对大型集群聚合建模。为了减少并发故障(例如,允许同时添加2条注释),您可以调整持久性机制,以允许集合不绑定。然而,这通常是一种最终可以保持一致的规则。如果
Post
隐藏到
Comment
之间有一点延迟,这真的很重要吗

选择最终一致性,
Post
Comment
是它们自己的AR。当
Post
被隐藏时,一个
PostHidden
事件被发送到消息传递机制,订阅者将负责使相关的
Comment
AR保持一致


另外,请注意,您可能根本不需要同步
Post.hidden
Comment.hidden
。由于
Comment
s可能只在
Post
的上下文中看到,因此我不知道UI如何允许查看隐藏
Post
注释。避免同步
隐藏
标志实际上允许取消隐藏
帖子
,同时将其
注释
恢复到
帖子
隐藏之前的状态,而无需做任何事。

首先,我必须同意plalx的最后一段,即需要同步
Post
Comment
中的隐藏标志。有人会假设用户界面会查看
帖子
,并意识到它是隐藏的,而不会费心获取/显示评论?但我很感激你可能只是在一个简单的例子上实践DDD理论

我也同意他关于最终一致性的说法。但是,对于本练习的要点,我认为没有必要添加它所需的基础设施,可以采取更简单的方法

我想说有两种方法可以做到这一点,选择取决于每个帖子可能有多少评论。免责声明:我是一名C#程序员,因此如果php语法错误,请原谅我(我假设它是php?)

  • 单骨料设计
  • 如果每个帖子不太可能有数百条评论,我会将
    Comment
    建模为
    post
    的子实体,其中
    post
    是唯一的聚合根。通过这种方式,隐藏注释不变量很容易实施:

    class Post {
    
        private $hidden;
        private $comments;
    
        public function isHidden() {
            return $this->hidden;
        }
    
        public function hide(){
            $hidden = true;
            foreach ($comments as $comment){
                $comment.hide();
            }
        }   
    
        public function addComment($comment){
            $comments.add($comment);
        }
    }
    
  • 单个聚合根
  • 如果可能有数百条评论被添加到一篇文章中,那么您需要将其建模为单个聚合。否则,Post聚合将变得太大,也许更重要的是(正如plalx所指出的),您可能会在同时添加多个注释的
    Post
    聚合上遇到并发冲突

    这样做将涉及使用来处理逻辑,而不是调用方使用聚合本身的方法:

    class PostService {
    
        private $postRepository;
        private $commentRepository;
    
        public function hidePost($postId) {
            $post = $postRepository.GetById($postId);
    
    
            $post.hide();
            $postRepository.save($post);
    
            //Method 1: update each comment
            $comments = $commentRepository.GetCommentsByPostId($postId);
            foreach($comments as $comment){
                $comment.hide();
                $commentRepository.save($comment);
            }
    
            //Method 2: create specific update method on repository with performant update query            
            $commentRepository.hideCommentsForPost($postId);
        }
    }
    
    请注意,聚合上的
    hide()
    方法不会公开使用。在C#中,这些方法被称为
    internal
    方法,这意味着只有同一程序集中的代码才能调用它们:关键是调用方必须使用
    PostService
    来隐藏帖子,而不是直接使用
    $post.hide()
    AR


    另外请注意,您不应在AR中直接引用其他AR。您应改为通过Id引用其他AR

    根据DDD中的常用设计原则,
    注释
    不应具有对
    Post
    的对象引用。如果你真的需要隐藏个人评论,如果他们的父项
    Post
    是隐藏的,那么就要明确(例如,通过一个长时间运行的流程/saga)。我不太确定你的域服务示例。如果有一个事务围绕着所有这些,那么就并发冲突而言,它并不比一个AR好多少。每个应收账款应在其自己的交易中进行修改。我遗漏了什么吗?如果有一个AR和一个同时添加大量注释的人,那么并发冲突很可能发生。此方法有单独的AR,因此可以添加新注释而不会产生并发冲突。我想我希望有人告诉我,在
    注释中保留对
    Post
    AR的引用没有问题,因为逻辑将在核心域中强制执行。所以“按ID引用AR”是我绝对不应该违反的规则之一。我将使用域服务来处理此类问题,或者最终按照建议将这些验证转移到上层。谢谢你@plalx和@david