我已经阅读了双调度模式,它可以将服务接口传递给聚合方法:https ://lostechies.com/jimmybogard/2010/03/30/strengthening-your-domain-the-double-dispatch-pattern/ , http://blog.jonathanoliver.com/dddd-double-dispatch/。
在我的域中,我有一个BitbucketIntegration
聚合,它是远程 bitbucket 帐户的本地副本,其中 包含一些额外的域特定数据。现在,我必须从云同步存储库和团队等,以便能够在它们上进行业务操作。在我的第一个实现中,我使用服务访问 Bitbucket Cloud,然后设置聚合的存储库、团队、帐户。通过这种方式,我将DDD与Anemic Domain Model混合在一起,因为一半的聚合状态是使用服务中的类似 setter 的方法设置的。使用Double Dispatch,我可以通过例如BitbucketService
接口到方法参数。这样,聚合可以更多地保护它的不变量,因为某些数据只能通过连接到其余服务来验证(例如,如果聚合的accessToken
,bitbucketAccount
和repositories
同步),这是服务的责任。还有一件事是accessToken
我的聚合中有一个字段,这只是一个技术问题。
是否有任何推荐的模式将远程资源的副本保存在 ddd 聚合中?另外,如何避免技术方面的影响?还是第一种使用域服务的方法足够好?
现在代码看起来像:
class BitbucketIntegration extends Aggregate<UUID> {
accountId: BitbucketId
repos: List<Repository>
localData: ...
// ... and more
Single integrateWith(accessToken, queryService) {
var id = queryService.getAccountAsync(accessToken);
var repos = queryService.getReposAsync(accessToken);
return Single.zip(id, repos,
(i, r) -> new BitbucketIntegratedEvent(accessToken, i, r))
.onSubscribe(event -> apply(event))
}
Observable doSomeBusinessLocally(data) { ... return events; }
// this is triggered by a saga
Single pollForChanges(queryService) {
var dataFromRemote = queryService.synchronizeAsync(this.accessToken);
....
return event;
}
}
class CommandHandler {
queryService: BitbucketService
Completable handle(integrateCmd) {
aggregate = repo.get(integrateCmd.id);
return aggregate.integrateWith(integrateCmd.accessToken, queryService)
.flatMap(event -> repo.store(event));
}
}
作为旁注,我只查询Bitbucket。
编辑: Martin Fowler 写了关于访问外部系统的文章,包括定义反腐败层,它将远程资源表示转换为域类型。