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);
}
...