从ddd聚合查询远程休息服务

时间:2018-01-06 16:32:12

标签: domain-driven-design ddd-service dddd

我已经了解了 Double Dispatch 模式,它可以将服务接口传递到聚合方法: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接口。这样,聚合可以更多地保护它的不变量,因为一些数据只能通过连接到其他服务来验证(例如,如果聚合accessTokenbitbucketAccountrepositories同步),这是服务的责任。另外一件事就是我的聚合中有一个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撰写了关于accessing an external system的文章,其中包括反腐败层的定义,它将远程资源表示转换为域类型。

1 个答案:

答案 0 :(得分:2)

如果您将基础结构服务注入到Aggregate中(通过构造函数或方法调用),那么您将不再拥有pure域模型。这甚至包括在域层中定义接口的服务。它会影响可测试性并引入对基础结构的依赖性。它还打破了Single responsibility principle,它迫使Aggregate知道它不需要的东西。

解决方法是之前调用服务,并将结果传递给聚合方法(即在应用程序层中)。