DDD - 第三方 API 接口应该在哪里?
DDD - Where should third-party API interfaces should be?
如果我们考虑一个标准的持久存储库,解决方案很简单。我们将 IStuffRepository 放在领域层,将 StuffRepositoryImplementation 放在基础设施层。
但是当我们想要包装第三方时,好的模式是什么API?
我们可以应用相同的模式,在领域层有一个 IStuffGateway,在基础设施层有一个 StuffGatewayImplementation。
但是这种方法有一个问题。当我们考虑持久层时,我们可以控制我们持久化的数据。但是当我们考虑第三方API时,我们没有控制权,这意味着我们可以尝试拥有某个接口签名,但它必须受到我们包装的内容的影响。因此,如果我们更改实现(将第三方替换为另一个),接口签名可能会更改,域也会更改。
另一种方法可能是将接口移到域外,并将其放入基础层及其实现。这样,应用层就可以毫无问题地使用它(并保持域完好无损)。但是这种方法从域中删除了重要的概念,从我的角度来看这似乎很糟糕。
对此有参考文献的意见吗?
我总是保持我的 Domain
对象 (Aggregates
) 纯净,没有副作用。这意味着我没有从 Domain
到任何其他层的任何依赖项。 persistence/repository 总是在 Infrastructure
中。 Application
层使用它来持久化 Aggregates
.
当我使用CQRS
时,我只保持write/command方面(Aggregates
)的纯净。 Readmodels
依赖并针对特定实现进行了优化。最近我用了很多MongoDB
来坚持。
当我不使用CQRS
时,我保持整个Aggregate
没有依赖(我别无选择,拆分将是CQRS
)。
因此,在所有情况下,Domain
不会执行任何 IO
,它没有副作用。这主要是因为在并发更新的情况下,我需要能够在 Aggregate
上安全地重新执行命令。
如果您决定使用接口,您应该使用 DIP:Domain
拥有 Interface
;这意味着 域决定方法的数量和签名 。
我同意康斯坦丁的观点。
您可以仍然将概念保留在您的域中,而不是 IO。应用层应该提供所需的域对象。您可以调用您的反腐败层 (IStuffGateway
) 并获取所需的对象,然后通过对您的域的一些调用传递这些对象。
如果这是一项常见任务,您可能需要引入一个应用程序服务 (IGetStuffAndCallDomainTask
) 来包装该位。
如果我们考虑一个标准的持久存储库,解决方案很简单。我们将 IStuffRepository 放在领域层,将 StuffRepositoryImplementation 放在基础设施层。
但是当我们想要包装第三方时,好的模式是什么API?
我们可以应用相同的模式,在领域层有一个 IStuffGateway,在基础设施层有一个 StuffGatewayImplementation。
但是这种方法有一个问题。当我们考虑持久层时,我们可以控制我们持久化的数据。但是当我们考虑第三方API时,我们没有控制权,这意味着我们可以尝试拥有某个接口签名,但它必须受到我们包装的内容的影响。因此,如果我们更改实现(将第三方替换为另一个),接口签名可能会更改,域也会更改。
另一种方法可能是将接口移到域外,并将其放入基础层及其实现。这样,应用层就可以毫无问题地使用它(并保持域完好无损)。但是这种方法从域中删除了重要的概念,从我的角度来看这似乎很糟糕。
对此有参考文献的意见吗?
我总是保持我的 Domain
对象 (Aggregates
) 纯净,没有副作用。这意味着我没有从 Domain
到任何其他层的任何依赖项。 persistence/repository 总是在 Infrastructure
中。 Application
层使用它来持久化 Aggregates
.
当我使用CQRS
时,我只保持write/command方面(Aggregates
)的纯净。 Readmodels
依赖并针对特定实现进行了优化。最近我用了很多MongoDB
来坚持。
当我不使用CQRS
时,我保持整个Aggregate
没有依赖(我别无选择,拆分将是CQRS
)。
因此,在所有情况下,Domain
不会执行任何 IO
,它没有副作用。这主要是因为在并发更新的情况下,我需要能够在 Aggregate
上安全地重新执行命令。
如果您决定使用接口,您应该使用 DIP:Domain
拥有 Interface
;这意味着 域决定方法的数量和签名 。
我同意康斯坦丁的观点。
您可以仍然将概念保留在您的域中,而不是 IO。应用层应该提供所需的域对象。您可以调用您的反腐败层 (IStuffGateway
) 并获取所需的对象,然后通过对您的域的一些调用传递这些对象。
如果这是一项常见任务,您可能需要引入一个应用程序服务 (IGetStuffAndCallDomainTask
) 来包装该位。