Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/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
Oop 我在理解DDD的过程中遇到了一个令人困惑的情况_Oop_Design Patterns_Domain Driven Design_Ddd Repositories_Ddd Service - Fatal编程技术网

Oop 我在理解DDD的过程中遇到了一个令人困惑的情况

Oop 我在理解DDD的过程中遇到了一个令人困惑的情况,oop,design-patterns,domain-driven-design,ddd-repositories,ddd-service,Oop,Design Patterns,Domain Driven Design,Ddd Repositories,Ddd Service,提前感谢您的帮助和关注 我的项目仅用于学习目的,我完全与DDD混淆,并有以下情况: 在我的领域里,有一种无处不在的语言,我有用户和文档。它说: - A user can create a document. One of the main purpose of my project is to provide users an ability to create different documents. I mean that the documents cannot exist without

提前感谢您的帮助和关注

我的项目仅用于学习目的,我完全与DDD混淆,并有以下情况:

在我的领域里,有一种无处不在的语言,我有用户和文档。它说:

- A user can create a document. One of the main purpose of my project is to provide users an ability to create different documents. I mean that the documents cannot exist without the users. So,I think that the process of a document creation belongs to my domain.
- A user can send a document for approval. It's one more thing that belongs to the domain. An approval process is one of the most important part of the project. It has its steps that other users must confirm.
- A user can approve a step of approval process.
- A user can reject a step of approval process.
这足以理解并回答我的问题:

用户可以包含以下方法是正常的吗:CreateDocument(params)、SendDocumentForApproval(docId)、ApproveApprovalDepofDocument(stepId)

我很喜欢它,因为它在代码中看起来有点奇怪

例如,对于文档创建过程,我们有如下内容:

    public async Task<bool> CreateDocumentCommandHandler(CreateDocumentCommand command)
{

    //We have our injected repositories
    User user = await _userRepository.UserOfId(command.UserId);

    Document document = User.CreateDocoment(command.*[Params for the document]);

    _documentRepostiory.Add(document);

     // It raises event before it makes a commit to the database
     // It gets event from an entity. The entity keeps it as readonly collection.
     // Here it raises DocumentCreatedEvent. This event contains logic which concerns
     // creation some additional entities for the document and log actions.
    await _documentRepository.UnitOfWork.SaveEntitiesAsync();
}
公共异步任务CreateDocumentCommandHandler(CreateDocumentCommand命令)
{
//我们有自己的知识库
User User=await\u userRepository.UserOfId(command.UserId);
Document Document=User.CreateDocoment(命令。*[Document的参数]);
_文档报告。添加(文档);
//它在提交到数据库之前引发事件
//它从实体获取事件。该实体将其保留为只读集合。
//这里它引发DocumentCreatedEvent。此事件包含与
//为文档和日志操作创建一些其他实体。
wait_documentRepository.UnitOfWork.SaveEntitiesAsync();
}
审批流程:

//The first try out to model this process:
public async Task<bool> SendDocumentForApprovalCommandHandler(SendDocumentForApprovalCommand command)
{
    //We have our injected repositories

    User user = await _userRepository.UserOfId(command.UserId);

    //Here I have some problems.
    //Is it okay that the method returns the document?
    //The method that is placed inside the User has this logic:
    //public Document SendDocumentForApproval(int docId)
    //{
    //   Document document = this.GetDocument(docId);
    //   
    //   //Inside this method ChangedStatusToApproving is created
    //   document.SetStatusToApproving();
    //   return document;
    //}
    Document document = User.SendDocumentForApproval(command.DocId);

    _documentRepostiory.Upadate(document);

     // It raises event before it makes a commit to the database
     // It gets event from an entity. The entity keeps it as readonly collection.
     // Here it raises ChangedStatusToApproving. This event contains logic which concerns
     // creation some additional entities for the document and log actions.
    await _documentRepository.UnitOfWork.SaveEntitiesAsync();
}
//Is it okay to do something like the command handler above?

//The second one:
public async Task<bool> SendDocumentForApprovalCommandHandler(SendDocumentForApprovalCommand command)
{
    //We have our injected repositories
    User user = await _userRepository.UserOfId(command.UserId);

    //The same one as we have in the previous method.
    //But here I don't want to put the logic about the changing status of the doucnent inside it.
    Document document = User.SendDocumentForApproval(command.DocId);
    //I see that it breaks the method above (SendDocumentForApproval)
    //Now It doesn't mean anything for our domain, does it?
    //It is only getter like User.GetDocument or we can even do it
    //by using repository - documentRepository.DocumentOfId(docId)
    document.SetStatusToApproving();

    _documentRepostiory.Upadate(document);

    await _documentRepository.UnitOfWork.SaveEntitiesAsync();
}

// So, I think the first one is better, isn't it? It follows the ubiquitous language. 

//And here is the final question: Why can't I do it like this:
public async Task<bool> SendDocumentForApprovalCommandHandler(SendDocumentForApprovalCommand command)
{
    //Here we don't want to use the userRepository. We don't need at all
    //Here as a consequence we also don't need a user entity
    //Everything what we need is:
    Document document = _documentRepository.DocOfId(command.DocId);
    document.ForApproval();

    _documentRepostiory.Upadate(document);

    await _documentRepository.UnitOfWork.SaveEntitiesAsync();
}
//I think that the last approach breaks the ubiquitous language and we're about to having an anemic model.
//But here we have only two queries to the database because we don't need a user.
//Which of the approaches is better? Why? How can I do it more correctly if I want to apply DDD?
//对该过程建模的第一次尝试:
公共异步任务SendDocumentForApprovalCommand处理程序(SendDocumentForApprovalCommand命令)
{
//我们有自己的知识库
User User=await\u userRepository.UserOfId(command.UserId);
//这里我有一些问题。
//方法返回文档可以吗?
//放置在用户内部的方法具有以下逻辑:
//公共文档SendDocumentForApproval(int docId)
//{
//Document Document=this.GetDocument(docId);
//   
////在该方法中,创建了ChangedStatusToApproving
//document.SetStatusToApproving();
//归还文件;
//}
文档=User.SendDocumentForApproval(command.DocId);
_文件调查。升级版(文件);
//它在提交到数据库之前引发事件
//它从实体获取事件。该实体将其保留为只读集合。
//在这里,它引发ChangedStatusToApproving
//为文档和日志操作创建一些其他实体。
wait_documentRepository.UnitOfWork.SaveEntitiesAsync();
}
//可以像上面的命令处理程序那样做吗?
//第二条:
公共异步任务SendDocumentForApprovalCommand处理程序(SendDocumentForApprovalCommand命令)
{
//我们有自己的知识库
User User=await\u userRepository.UserOfId(command.UserId);
//与前面的方法相同。
//但在这里,我不想把关于公司不断变化的状态的逻辑放在里面。
文档=User.SendDocumentForApproval(command.DocId);
//我发现它破坏了上述方法(SendDocumentForApproval)
//现在它对我们的领域没有任何意义,是吗?
//它只是像User.GetDocument一样的getter,我们甚至可以这样做
//通过使用repository-documentRepository.DocumentOfId(docId)
document.SetStatusToApproving();
_文件调查。升级版(文件);
wait_documentRepository.UnitOfWork.SaveEntitiesAsync();
}
//所以,我认为第一个更好,不是吗?它遵循普遍存在的语言。
//最后一个问题是:为什么我不能这样做:
公共异步任务SendDocumentForApprovalCommand处理程序(SendDocumentForApprovalCommand命令)
{
//这里我们不想使用userRepository,我们根本不需要它
//因此,我们也不需要用户实体
//我们需要的一切是:
documentdocument=\u documentRepository.DocOfId(command.DocId);
文件。用于批准();
_文件调查。升级版(文件);
wait_documentRepository.UnitOfWork.SaveEntitiesAsync();
}
//我认为最后一种方法打破了普遍存在的语言,我们即将有一个贫血模型。
//但是这里我们只有两个对数据库的查询,因为我们不需要用户。
//哪种方法更好?为什么?如果我想应用DDD,我如何才能更正确地执行此操作?
我想更详细地解释我的想法。 让我们看看用户。他们管理文档。没有用户,文档无法存在。这是否意味着用户是聚合根用户,因为我们需要创建、更新和删除其聚合

文档也是聚合根,因为它包含一个Approval进程。没有文档,ApprovalProcess无法存在

document.SendDocumentForApproval(command.UserId)
_documentRepository.Update(document);
这是否意味着我需要这样做:

public async Task<bool> SendDocumentForApprovalCommandHandler(SendDocumentForApprovalCommand command)
{
    Document document = _documentRepository.DocumentOfId(command.DocId);

    document.SendForApproval();

    _documentRepository.SaveChangesAsync();//Raise a domain event - SentDocumentForApprovalEvent
}

// Here we have a handler for the event SentDocumentForApprovalEvent
public async Task SentDocumentForApprovalEventHandler(SentDocumentForApprovalEvent sentDocumentForApprovalEvent)
{
    //Now I want to create an approval process for the document
    //Can I do the next thing:
    ApprovalProcess process = new ApprovalProcess(sentDocumentForApprovalEvent.DocId);

    _approvalProcessRepository.Add(process);

    _approvalProcessRepository.SaveEntitiesAsync();//Raise a domain event - InitiatedApprovalProcessEvent

    //Or Should I create the approval process through Document?

    //Looks terrible due to we need to call the repostiory amd
    ApprovalProcess process = Document.InitiateApprovalProcess(sentDocumentForApprovalEvent.DocID);//Static method

    _approvalProcessRepository.Add(process);

    _approvalProcessRepository.SaveEntitiesAsync();

    //log
}

// Here we have a handler for the event InitiatedApprovalProcessEvent
public async Task InitiatedApprovalProcesEventHandler(SentDocumentForApprovalEvent sentDocumentForApprovalEvent)
{
    //The same question as we have with handler above.
    //Should I create steps trough the approval process or just with the help of constructor of the step?

    //log
}
公共异步任务SendDocumentForApprovalCommand处理程序(SendDocumentForApprovalCommand命令)
{
documentdocument=\u documentRepository.DocumentOfId(command.DocId);
document.SendForApproval();
_documentRepository.SaveChangesSync();//引发域事件-SentDocumentForApprovalEvent
}
//这里我们有一个事件SentDocumentForApprovalEvent的处理程序
公共异步任务SentDocumentForApprovalEventHandler(SentDocumentForApprovalEvent SentDocumentForApprovalEvent)
{
//现在我想为文档创建一个审批流程
//我能做下一件事吗:
ApprovalProcess流程=新的ApprovalProcess(sentDocumentForApprovalEvent.DocId);
_approvalProcessRepository.Add(流程);
_approvalProcessRepository.SaveEntitiesAsync();//引发域事件-InitiatedApprovalProcessEvent
//还是应该通过文档创建审批流程?
//看起来很糟糕,因为我们需要打电话给报告室
ApprovalProcess process=Document.InitiateApprovalProcess(sentDocumentForApprovalEvent.DocID);//静态方法
_approvalProcessRepository.Add(流程);
_a
document.SendDocumentForApproval(command.UserId)
_documentRepository.Update(document);
class User {
    private UserId id;
    private String name;    

    User(String name) {
        this.id = new UserId();
        this.name = name;            
    }

    Document createDocument(String name) {
        Document document = new Document(name);        
        document.createdBy(this);
        return document;
    }

    Document approve(Document document) {
        document.approved();
        return document;
    }
}

class Document {
    private DocumentId id;
    private String name;
    private UserId userId;
    private Boolean isApproved;

    Document(String name) {
        this.id = new DocumentId();
        this.name = name;
    }

    void createdBy(UserId userId) {
        this.userId = userId;
    }    

    void approved() {
        this.isApproved = true;
    }

}

// User creation
User user = new User("Someone");
userRepository.save(user);

//Document creation
User user = userRepository.find(new UserId("some-id"))
Document document = user.createDocument("important-document")
documentRepository.save(document)

// Approval
User user = userRepository.find(new UserId("some-id"))
Document document = documentRepository.find(new DocumentId("some-id")) 
document = user.approve(Document)