DDD:逻辑应该去哪里测试实体的存在? [英] DDD: where should logic go that tests the existence of an entity?

查看:160
本文介绍了DDD:逻辑应该去哪里测试实体的存在?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在重构应用程序,并试图找出某些逻辑应该适合的地方.例如,在注册过程中,我必须根据用户的电子邮件地址检查用户是否存在.由于这需要测试用户是否存在于数据库中,因此似乎该逻辑不应与该模型联系在一起,因为它的存在是由它是否存在于数据库中决定的.

但是,我将在存储库中有一个方法,该方法负责通过电子邮件等方式获取用户.如果存在的话,这将处理有关检索用户的部分.从用例的角度来看,注册似乎是一个用例场景,因此似乎应该有一个带注册方法的UserService(应用程序服务),该方法将调用存储库方法,然后执行逻辑确定返回的用户实体是否为是否为空.

就DDD而言,我采用这种方法是否正确?我是否以错误的方式看待这种情况?如果是这样,我应该如何修改自己的想法?

此链接是作为可能的解决方案而提供的,在何处检查用户电子邮件是否还没有退出?.它确实有帮助,但似乎并不能解决问题.我似乎在本文中缺少的是谁将负责在聚合根上调用CreateUserService,应用程序服务或方法,将CreateUserService对象与任何其他相关参数一起注入该方法中? >

如果答案是应用程序服务,似乎您是通过将域服务移出域层来进行某种封装的.另一方面,采用其他方式意味着必须将存储库注入到域服务中.这两个选项中哪一个更可取,并且更符合DDD?

解决方案

我认为最适合该行为的是域服务. DS可以访问持久性,因此您可以检查是否存在或唯一. 检查此博客条目以获取更多信息.

即:

public class TransferManager
    {
        private readonly IEventStore _store;
        private readonly IDomainServices _svc;
        private readonly IDomainQueries _query;
        private readonly ICommandResultMediator _result;

        public TransferManager(IEventStore store, IDomainServices svc,IDomainQueries query,ICommandResultMediator result)
        {
            _store = store;
            _svc = svc;
            _query = query;
            _result = result;
        }

        public void Execute(TransferMoney cmd)
        {
            //interacting with the Infrastructure
            var accFrom = _query.GetAccountNumber(cmd.AccountFrom);

            //Setup value objects
            var debit=new Debit(cmd.Amount,accFrom);

            //invoking Domain Services
            var balance = _svc.CalculateAccountBalance(accFrom);
            if (!_svc.CanAccountBeDebitted(balance, debit))
            {
                //return some error message using a mediator
                //this approach works well inside monoliths where everything happens in the same process 
                _result.AddResult(cmd.Id, new CommandResult());
                return;
            }

            //using the Aggregate and getting the business state change expressed as an event
            var evnt = Transfer.Create(/* args */);

            //storing the event
            _store.Append(evnt);

            //publish event if you want
        }
    }

来自 http://blog.sapiensworks. com/post/2016/08/19/DDD-Application-Services-Explained

I am in the process of refactoring an application and am trying to figure out where certain logic should fit. For example, during the registration process I have to check if a user exists based upon their email address. As this requires testing if the user exists in the database it seems as if this logic should not be tied to the model as its existence is dictated by it being in the database.

However, I will have a method on the repository responsible for fetching the user by email, etc. This handles the part about retrieval of the user if they exist. From a use case perspective, registration seems to be a use case scenario and accordingly it seems there should be a UserService (application service) with a register method that would call the repository method and perform if then logic to determine if the user entity returned was null or not.

Am I on the right track with this approach, in terms of DDD? Am I viewing this scenario the wrong way and if so, how should I revise my thinking about this?

This link was provided as a possible solution, Where to check user email does not already exits?. It does help but it does not seem to close the loop on the issue. The thing I seem to be missing from this article would be who would be responsible for calling the CreateUserService, an application service or a method on the aggregate root where the CreateUserService object would be injected into the method along with any other relevant parameters?

If the answer is the application service that seems like you are loosing some encapsulation by taking the domain service out of the domain layer. On the other hand, going the other way would mean having to inject the repository into the domain service. Which of those two options would be preferable and more in line with DDD?

解决方案

I think the best fit for that behaviour is a Domain Service. DS could access to persistence so you can check for existence or uniquenes. Check this blog entry for more info.

I.e:

public class TransferManager
    {
        private readonly IEventStore _store;
        private readonly IDomainServices _svc;
        private readonly IDomainQueries _query;
        private readonly ICommandResultMediator _result;

        public TransferManager(IEventStore store, IDomainServices svc,IDomainQueries query,ICommandResultMediator result)
        {
            _store = store;
            _svc = svc;
            _query = query;
            _result = result;
        }

        public void Execute(TransferMoney cmd)
        {
            //interacting with the Infrastructure
            var accFrom = _query.GetAccountNumber(cmd.AccountFrom);

            //Setup value objects
            var debit=new Debit(cmd.Amount,accFrom);

            //invoking Domain Services
            var balance = _svc.CalculateAccountBalance(accFrom);
            if (!_svc.CanAccountBeDebitted(balance, debit))
            {
                //return some error message using a mediator
                //this approach works well inside monoliths where everything happens in the same process 
                _result.AddResult(cmd.Id, new CommandResult());
                return;
            }

            //using the Aggregate and getting the business state change expressed as an event
            var evnt = Transfer.Create(/* args */);

            //storing the event
            _store.Append(evnt);

            //publish event if you want
        }
    }

from http://blog.sapiensworks.com/post/2016/08/19/DDD-Application-Services-Explained

这篇关于DDD:逻辑应该去哪里测试实体的存在?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆