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_Domain Driven Design - Fatal编程技术网

Oop DDD:我可以将域服务作为聚合构造函数的参数传递吗

Oop DDD:我可以将域服务作为聚合构造函数的参数传递吗,oop,domain-driven-design,Oop,Domain Driven Design,我有一个维护其他系统(媒体)帐户的域。 首先,我导出了以下聚合根 public class Account extends Entity { private AccountId accountId; private TenantId tenantId; private LoginAccount loginAccount; private Media media; private LoginValidity validity;

我有一个维护其他系统(媒体)帐户的域。
首先,我导出了以下聚合根

public class Account extends Entity {
    
    private AccountId accountId;
    private TenantId tenantId;
    private LoginAccount loginAccount;
    private Media media;
    private LoginValidity validity;
    
    
    public Account(TenatId shopId, Media media, LoginAccount loginAccount) {
        this.accountId = new AccountId(); 
        this.setTenatId(shopId);
        this.set(media);
        this.setLoginValidity(LoginValidity.NOT_REQUESTED);
    }
    
    
    public void validateLogin(LoginValidationService loginValidationService) {
        LoginValidity validity = loginValidationService.validateLoginFor(media,loginAccount);
        setLoginValidity(validity);
        
        //TO-DO EVENT PUBLISHING
    }
    
    public void changeLoginAccount(LoginAccount loginAccount) {
        setLoginAccount(loginAccount);
        setLoginValidity(LoginValidity.NOT_REQUESTED);
        
        //TO-DO EVENT PUBLISHING?
    }

    ...Setters
}

我还将
LoginValidationService
导出为域服务。
LoginValidationService
使用
媒体确定策略(策略)

然后我还导出了两个业务逻辑(不变量)

  • 当用户添加
    帐户时,必须进行登录验证
  • 当用户更改登录时,必须进行登录验证
我的问题是,对于第一个不变量,
LoginValidationService
(域服务)可以是聚合根的构造函数的参数,如下所示

public class AccountApplicationService {
   private LoginValidationService loginValidationService;
   private AccountRepository accountRepository;

   public Account createAccount(CreateAccountCommand command) {
        TenantId tenantId = new TenantId(command.getTenantId());
        Media media = mediaService.mediaFrom(command.getMediaId());
        
        Account account = new Account(tenantId, 
                                     media,
                                     command.getLoginAccount(),
                                     loginValidationService);
        
        accountRepository.save(account);
        return ccount;
   }
   ...
}
是否存在上述模式?(将域服务传递给构造函数)这是DDD的正确方法吗

我是否必须导出第一个不变量作为用例?像这样,

public class AccountApplicationService {
   private LoginValidationService loginValidationService;
   private AccountRepository accountRepository;

    public Account createAccountAndValidateLogin(CreateAccountAndValidateLoginCommand command) {
        TenantId tenantId = new TenantId(command.getTenantId());
        Media media = mediaService.mediaFrom(command.getMediaId());
        
        MediaAccount mediaAccount = new MediaAccount(tenantId,media,command.getLoginAccount());
        mediaAccount.validateLogin(loginValidationService);
        
        mediaAccountRepository.save(mediaAccount);
    }
   ...
}
请给我任何建议

-----------编辑------------
我添加帐户的构造函数代码。LoginValidationService不是帐户的成员

我可以将域服务作为聚合构造函数的参数传递吗

是的,但从长远来看,这会让你的生活更艰难

聚合是一组相关对象,我们将其视为一个单元,用于数据更改。-埃文斯,2003年

然而,域服务不会改变——它们是无状态的,“任何客户端都可以使用特定服务的任何实例,而不考虑该实例的单独历史记录。”

因此,以这种方式混合模式在两个方面有点奇怪;将服务包含为聚合的一个成员表明它发生了变化,同时也意味着此聚合与服务的特定实例具有特殊关系,这与它们不可互换的概念相矛盾


我不清楚在将服务嵌入到聚合中的设计中有什么补偿优势。

登录有效性作为
帐户
聚合构造函数参数传递是一个解决方案

public Account createAccount(CreateAccountCommand command) {
        TenantId tenantId = new TenantId(command.getTenantId());
        Media media = mediaService.mediaFrom(command.getMediaId());
        LoginValidity loginValidity = 
            loginValidationService.validateLoginFor(media,command.getLoginAccount());

        Account account = new Account(tenantId, 
                                     media,
                                     command.getLoginAccount(),
                                     loginValidity);
        
        accountRepository.save(account);
        return ccount;
}


我认为验证帐户是实体自己无法完成的事情,因此很明显是域服务的责任,然后我会在用例流逻辑中看到,或者,您可以使用负责验证和创建帐户的域服务创建帐户,并将业务逻辑封装在域服务中,而不是用例中。

我为
帐户
创建的
帐户
无法保持自身,因此我派生了
帐户供应服务
(域服务)。应用程序服务代码如下

...

public Account createAccount(CreateAccountCommand command) {
        
        return AccountProvisioningService.provisionAccount(
             command.getTenantId(), command.getMediaId(), command.getLoginAccount());
    }


public void changeLoginAccount(ChangeLoginAccountCommand command) {
        Account account = existingAccount(command.getShopId(),command.getAccountId());
        LoginValidity loginValidity = loginValidationService.validateLoginFor(Account.media(), command.getLoginAccount());
        account.changeLoginAccount(command.getLoginAccount(),loginValidity);
        
        AccountRepository.save(account);
    }
...


我的意思不是说
LoginValidationService
Account
聚合的成员。
Account
只使用
LoginValidationService
来确定
LoginValidity
。构造函数代码将是
this.setLoginValidity(LoginValidationService.validatelogfor(media,loginAccount))
changeLoginAccount(LoginAccount LoginAccount)
将更改为这样的签名
changeLoginAccount(LoginAccount LoginAccount,LoginValidationService LoginValidationService)
。看起来不错。
Media
也来自
MediaService
(域服务)。我发现了一个用于创建的附加不变量,因此我派生了
AccountProvisionService
(域服务)。我必须小心不要成为一个贫血模型,但在这一点上它看起来不错。
...

public Account createAccount(CreateAccountCommand command) {
        
        return AccountProvisioningService.provisionAccount(
             command.getTenantId(), command.getMediaId(), command.getLoginAccount());
    }


public void changeLoginAccount(ChangeLoginAccountCommand command) {
        Account account = existingAccount(command.getShopId(),command.getAccountId());
        LoginValidity loginValidity = loginValidationService.validateLoginFor(Account.media(), command.getLoginAccount());
        account.changeLoginAccount(command.getLoginAccount(),loginValidity);
        
        AccountRepository.save(account);
    }
...