15

OHS ... Open Host Service
AL ... 应用层
ACL ... AntiCorruption Layer
BC ... 限界上下文

1.

这里我用单向这个词,当我们的 OHS的公共接口只能被外部BC调用我们的系统,而我们的BC不能调用外部系统时

同样,当我们的OHS 的公共接口可以被外部BC 使用来调用我们的系统时,我将使用术语双向,但它也可以被我们的BC 使用来调用外部系统

a) OHS是 单向的还是也可以是双向的?我会说它只能是单向的?

b) 同样,AL是 单向的还是也可以是双向的?我会说它只能是单向的?

2.我假设OHS不会取代AL,而是位于Application services/AL之上?

3.

a) OHS是否也应该用于作为同一应用程序一部分的 BC 之间的通信,还是应该用于与外部BC 的通信?无论答案如何,请详细说明您的推理?

b)假设相互通信的 BC 是同一应用程序的一部分,并假设我们不使用OHS - 这些 BC 是否应该直接相互通信(即 BC 会调用ACL,而后者又会直接调用 BC )或通过AL(即 BC 会调用ACL,后者会调用AL,然后会直接调用 BC )?

我认为这些 BC 应该直接通信而不是通过AL进行通信,因为它可能会使AL 的接口膨胀并且还可能将内部功能暴露给外部系统?

4.

Eric Evan 的 DDD 书,第 页。375:

Open Host Service 使用标准化协议进行多方集成。它使用域模型在系统之间进行交换,即使这些系统内部可能不使用该模型。

a) 我假设我们的OHS 应该只使用我们 应用程序的域模型作为其自身模型的基础?换句话说,OHS不应该使用应用程序的域模型,而应该只是基于它自己的模型

b) 由于我们的OHS 有它自己的模型(通常基于Core Domain,不管它是什么),我假设我们还应该定义一个位于OHS和我们应用程序的其余部分之间的翻译/反腐败层?

c)应用程序服务的参数返回值是否根据应用程序的域模型定义?

5.

BC 是否总是使用Infrastructure 服务来调用另一个 BC (当然如果 BC 使用ACL,那么 BC 会调用ACL,这反过来会调用Infrastructure layer,然后会调用另一个 BC ),无论另一个 BC 是外部的还是同一应用程序的一部分?

谢谢

欧乐汇:

1.

1b) ACL 是双向的,因为数据流向任一方向 - 当您向外部服务发送消息或解释从所述服务接收到的消息时。

a) 通过“或解释从所述服务接收到的消息”,您仅表示我们的ACL可以从被调用的外部BC接收回复(即返回值),或者您是否还表示发送消息的同一ACL(代表我们的BC )也可以在外部BC 呼叫我们的BC 时解释消息?

b) 如果是前者,那么从这个意义上说,OHS是否也是双向的,因为外部系统调用的OHS 服务也可以将回复(即返回值)发送回这些外部系统?如果是后者,在4b)中你说OHS本身也充当翻译器,这表明我们的BC用于调用外部系统的ACL在外部系统调用我们的 BC时也不会使用,这意味着ACL不能是双向的吗?

3.

3b)假设相互通信的 BC 是同一应用程序的一部分,并假设我们不使用 OHS - 这些 BC 是否应该直接相互通信(即 BC 将调用 ACL,而 ACL 又会直接调用 BC)还是通过 AL(即 BC 会调用 ACL,ACL 会调用 AL,然后会直接调用 BC)?

如果不使用 OHS,请调用其他 BC 的应用程序服务。

a) 所以你是说 BC 应该调用ACL,它会调用AL,然后它会直接调用另一个 BC?

b)同一个应用程序中的 BC 是否共享同一个AL

c) 如果内部BC 确实共享相同的AL,这是否意味着我们可能被迫定义一些 应用程序服务,其唯一目的是使内部BC 能够相互通信(因此外部客户端并不意味着调用这些特定的应用服务)。因此,这些应用程序服务不会向外部客户端公开内部功能吗?

澄清:我知道外部客户端只有在引用包含我们的应用程序服务的dll时才能直接调用我们的应用程序服务,但如果某些客户端确实有对此类dll的引用,那么他们可能会调用旨在成为的应用程序服务仅由内部BC 相互呼叫使用?

4.

b)

我假设我们还应该在 OHS 和我们的应用程序的其余部分之间定义一个翻译/反腐败层?

实际上,OHS 就是那个翻译层。它将所有行为委托给应用程序服务,在此过程中适应用于实现 OHS 的特定技术。

根据 Evans 的说法,OHS应该只使用底层领域模型作为其自身模型的基础,这意味着这两个模型应该是独立的“实例”。

域模型应该完全忽略除它们建模的域之外的任何内容。相同的规则是否也适用于OHS 模型?换句话说,OHS 模型不应该不知道其他层和域,因此它不应该将消息从自己的模型转换为底层AL封装的域模型吗?

C)

应用程序服务的参数和返回值是否根据应用程序的域模型定义?

根据 DTO 定义接口

假设Application Services 的接口是根据 DTO 定义的:OHS是根据OHS 模型定义的,Application Services封装了领域模型,但是什么模型定义了这些 DTO?换句话说,这些 DTO 是OHS 模型的一部分,是由AL封装的域模型的一部分还是...?

5.

BC 是否总是使用基础设施服务来调用另一个 BC(当然如果 BC 使用 ACL,那么 BC 会调用 ACL,ACL 反过来会调用基础设施层,然后会调用另一个 BC),无论另一个 BC 是外部的还是同一应用程序的一部分?

可以说,不管被调用的BC是内部的还是外部的,你还是在某种程度上使用了ACL。

a) 不应该只在外部模型有泄漏到我们模型中的危险时才应用ACL吗?

b)由于内部BC(同一应用程序中的 BC)应该通过AL相互通信,我假设您会让这些 BC通过基础设施层调用AL,因为域层不应该对上层有任何依赖(即AL )?

c) 所以你不同意@mrhobo,它指出内部BC 应该直接相互通信(如果 BC 使用ACL,那么 BC 将直接调用ACL,而 ACL 又会调用另一个 BC)而不是通过AL?为什么?

EULERFX,第二次更新:

1.

b)

如果是后者,在4b)中你说OHS本身也充当翻译器,这表明当外部系统调用我们的BC时,我们的BC用于调用外部系统的ACL也不会被使用,这意味着ACL不能是双向的?

OHS 执行的翻译虽然类似于 ACL,但在性质上有所不同,因为它具有技术特征。

那么埃文斯(第 368 页)“ACL 可以是双向的”是什么意思,因为如果按照您的建议实现通信,那么ACL永远不会是双向的(而BC1使用的 ACL1可以接收来自BC2的回复ACL1永远不会在BC2调用BC1时使用,即使BC1BC2都是内部的- 请注意我知道BC2将使用自己的ACL,我只是指出埃文斯谈论双向 ACL。换句话说,他的意思是当BC2调用BC1时,这个调用会被ACL1接收)?

3.

c) 如果内部 BC 确实共享同一个 AL,这是否意味着我们可能被迫定义一些应用程序服务,其唯一目的是使内部 BC 能够相互通信(因此外部客户端并不意味着调用这些特定的应用程序服务 )。因此,这些应用程序服务不会向外部客户端公开内部功能吗?

如上所述,BC 应该共享应用程序服务,即使它们是内部的。这没有多大意义。

a)我认为这是一个错字,你的意思是应该不应该而不是应该

b)内部BC 也不共享OHS吗?

c) 如果内部BC 通过OHS相互通信,我们会不会面临与这些 BC 通过AL通信时相同的问题(即,我们可能被迫定义一些OHS 服务,其唯一目的是使内部BC 能够相互通信其他,因此这些OHC 服务可能会将内部功能暴露给外部客户端)?

5.

一个)

不应该只在外部模型有泄漏到我们模型中的危险时才应用 ACL 吗?

是的,但是如果您调用某个外部 BC,情况总是如此。如果 BC 是本地拥有的,那么您可以就模型(共享内核)达成一些相互协议,但将它们解耦通常仍然更容易。

我认为即使解耦,如果两个 BC 之间的公共接口足够简单(至少我是这么理解 Evans 的),我们仍然可以有一个简单的转换层(而不是完整的ACL )?

霍博

3.

b)

假设相互通信的 BC 是同一个应用程序的一部分,并假设我们不使用 OHS - 这些 BC 是否应该直接相互通信(即 BC 将调用 ACL,而 ACL 又会直接调用 BC)或通过AL(即 BC 会调用 ACL,ACL 会调用 AL,然后会直接调用 BC)?

AL 旨在将域与其用户和使用方式分开。生活在同一个应用程序中的不同 BC 不应该通过这些层进行通信,而应该是同一个域层的一部分。

所以你不同意@eulerfx关于内部BC 通过AL互相呼叫的问题?为什么?

2)

我假设 OHS 不会取代 AL,而是位于应用程序服务/AL 之上?

它可以位于 AL 之上,但也可以直接位于 BC 之上。AL 和 OHS 非常相似。如果 BC 的所有使用都依赖于 OHS,在我看来,几乎不需要在 AL 之间创建一个中间层。

您能否澄清在什么情况下 BC 的所有使用仅取决于OHS以及何时还取决于AL

4.

b)

由于我们的 OHS 有它自己的模型(通常基于核心域,不管它是什么),我假设我们还应该定义一个位于 OHS 和我们应用程序的其余部分之间的翻译/反腐败层?

您将需要适配器在域模型和交互模型之间进行转换,是的。然而,ACL 旨在以这样一种方式集成两个 BC,即使用 ACL 的 BC 不知道另一个 BC 的存在。这对于使用 OHS 的客户端来说很方便,但不应该在服务器端的 OHS 和 BC 之间进行。

换句话说,OHSAL之间的翻译器不应该是ACL,而应该只是一个“常规”翻译器

4

2 回答 2

6

1.a) OHS 是单向的还是也可以是双向的?我会说它只能是单向的?

确切地说,一个需要通过自己的接口访问其他服务的服务根本就不是一个服务。

1.b) 同样,AL 是单向的还是也可以是双向的?

同样,需要访问使用该层的层的层根本不是层。与所有分层架构一样:依赖关系只有一种方式。

2) 我假设 OHS 不会取代 AL,而是位于应用程序服务/AL 之上?

它可以位于 AL 之上,但也可以直接位于 BC 之上。AL 和 OHS 非常相似。如果 BC 的所有使用都依赖于 OHS,在我看来,几乎不需要在 AL 之间创建一个中间层。

3.a) OHS 是否也应该用于作为同一应用程序一部分的 BC 之间的通信,还是应该仅用于与外部 BC 的通信?无论答案如何,请详细说明您的推理?

这完全取决于您的用例、要求和环境。OHS 的构建和维护通常并不便宜,并且通常为了成本和简单性而避免使用。但是,在同一个应用程序中拥有 OHS 可能有充分的理由,例如,当出于可用性或性能原因需要分发应用程序时,或者当多个团队在应用程序的不同可互换部分的不同位置工作时。

3.b)假设相互通信的 BC 是同一应用程序的一部分,并假设我们不使用 OHS - 这些 BC 是否应该直接相互通信(即 BC 将调用 ACL,而 ACL 又会直接调用BC)还是通过 AL(即 BC 会调用 ACL,ACL 会调用 AL,然后会直接调用 BC)?

BC 可以通过许多不同的方式直接和间接地进行交流。这些是 DDD 概述的模式:客户/供应商、共享内核、反腐败层等。需要明确的是:应用层不是其中之一。AL 旨在将域与其用户和使用方式分开。生活在同一个应用程序中的不同 BC不应该通过这些层进行通信,而应该是同一个域层的一部分。应该使用哪种模式再次集成 BC 取决于。ACL 在处理遗留代码时会派上用场,但如果您像大多数应用程序开发一样同时控制两个 BC,那么 ACL 肯定不是最佳解决方案。

4.a) 我假设我们的 OHS 应该只使用我们应用程序的域模型作为其自身模型的基础?换句话说,OHS 不应该使用应用程序的域模型,而应该只是基于它自己的模型?

是的。如果您不将域模型与交互模型分开,那么您就不再是域建模了。交互模型通常涉及与领域无关的概念。

4.b) 由于我们的 OHS 有它自己的模型(通常基于核心域,不管它是什么),我假设我们还应该定义一个位于 OHS 和我们应用程序的其余部分之间的翻译/反腐败层?

您将需要适配器在域模型和交互模型之间进行转换,是的。

然而,ACL 旨在以这样一种方式集成两个 BC,即使用 ACL 的 BC 不知道另一个 BC 的存在。这对于使用 OHS 的客户端来说很方便,但不应该在服务器端的 OHS 和 BC 之间进行。

4.c) 应用程序服务的参数和返回值是否根据应用程序的域模型定义?

他们可以是的。经常这样做是为了节省时间,但它不应导致您的域模型成为应用程序感知的。

5)BC是否总是使用基础设施服务来调用另一个BC(当然如果BC使用ACL,那么BC会调用ACL,ACL又会调用基础设施层,然后调用另一个BC),不管那个其他BC是否外部或同一应用程序的一部分?

BC 之间的通信并不总是必须跨层。正如我之前所说,多个 BC 可以存在于同一个域层中,并且可以通过 DDD 概述的多种方式进行集成。这适用于 BC 是同一非分布式应用程序的一部分时。当 BC 分布时,这些 BC 将需要使用基础设施层与外部对应物进行交互。

更新

所以你不同意@eulerfx 关于内部 BC 通过 AL 互相呼叫的问题?为什么?

是的,我好像有。

应用程序层的职责是从其他类型的逻辑(如表示和基础架构逻辑)中抽象出应用程序逻辑,并在应用程序中创建单点真实性。应用层模式不是由 DDD 定义的,也不是 BC 集成模式,如共享内核、顺从者、客户/供应商和反腐败层。一个应用程序有一个应用程序层。当您将应用程序层视为 BC 周围的立面时,eulerfx 的建议并没有错,这通常是,但这根本不是应用程序层的定义。如果你愿意,请查一下。

您能否澄清在什么情况下所有 BC 的使用仅取决于 OHS,何时还取决于 AL?

AL 和 OHS 非常相似。AL 用于在应用程序中使用,而 OHS 用于外部通信。两者都是门面。当您的应用程序没有表示层,只有一个 OHS 时,创建一个应用程序层在两者之间是没有意义的。当应用程序具有表示层但也通过 OHS 公开其 BC 时,表示层将使用 AL,而外部系统将使用 OHS,而 OHS 又将使用 AL。

如果 AL 存在,OHS 应该依赖于 AL,因为 AL 应该是一个单一的事实点。

换句话说,OHS 和 AL 之间的翻译器不应该是 ACL,而只是一个“常规”翻译器?

确切地。

ACL 是 BC 的一部分,但实际上是从另一个 BC 获取其信息。这将所有杂乱的集成部分抽象出来,并使 BC 可以以适合域的方式进行编码。ACL 可防止 BC 因这些集成问题而损坏。

这是一个实际的例子:https ://softwareengineering.stackexchange.com/questions/184464/what-is-an-anti-corruption-layer-and-how-is-it-used

于 2013-05-28T19:06:04.307 回答
3

1a) 通过 BC 自己的开放主机服务调用外部系统是没有意义的。使用您的术语,开放主机服务始终是单向的。

1b) ACL 是双向的,因为数据流向任一方向 - 当您向外部服务发送消息或解释从所述服务接收到的消息时。

2) 是的,开放主机服务位于应用程序服务之上。在六边形架构中,它形成一个端口/适配器,使应用层适应 HTTP。

3a) 这取决于并确定最佳解决方案,考虑 OHS 的优点和缺点。主要好处是封装,当与已发布的语言结合使用时,可以创建一个标准化的接口来访问服务,而不管技术如何。OHS 通常比内部接口更稳定。一个缺点是实施和维护 OHS 所需的工作量,因为它实际上是另一层。

3b) 如果不使用OHS,调用其他BC 的应用服务。该服务可以通过完全由 DTO 形成接口来完全封装组成域。或者,如果谨慎使用,您可以直接返回域对象。AL 在域层上形成一个外观,简化了接口。直接调用域对象过于细化。

4a) OHS 应该源于它封装的领域模型,但它可能与其客户使用的模型不同,这就是客户应该创建自己的 ACL 的原因。

4b) 实际上,OHS 将是那个翻译层。它将所有行为委托给应用程序服务,在此过程中适应用于实现 OHS 的特定技术。

4c) 见上文。他们可以,但是太多的领域知识可能会泄漏。相反,您可以根据 DTO 定义接口 - 为查询读取模型,为行为读取命令对象。

5)可以说,无论被调用的BC是内部的还是外部的,你还是在一定程度上使用了ACL。

更新

1a) 前者。

1b) 如果外部 BC 调用本地 OHS,那么它必须根据本地 OHS 发布的语言来调用它 - 不需要本地 ACL。外部 BC 中的 ACL 将执行从外部 BC 的模型到本地 OHS 语言的翻译。OHS 执行的翻译虽然类似于 ACL,但在性质上有所不同,因为它具有技术特征。它是转换,或者更好的是,将域模型改编为 HTTP。

3a) 是的,被调用的 AL 将是另一个 BC 的一部分 - 另一个 BC 域模型的外观。然而,这种方法的一个缺点是托管应用程序必须为所有正在交互的 BC 配置依赖关系。

3b) 不会。每个 BC 都会有一组应用服务,封装相应的领域模型。当不使用 OHS 时,BC 之间的通信将跨越这些应用程序服务和 ACL。

3c) 如上所述,BC 应该共享应用程序服务,即使它们是内部的。这没有多大意义。

如果您可以访问包含应用程序服务的 DLL,那么您真的可以做任何事情。这就是 OHS 提供更好的封装和互操作性的原因。

4b) OHS 确实有自己的模型,但是这个模型是基于领域模型的。不同之处在于 OHS 是域模型和某些服务技术之间的适配器。它旨在公开域模型。因此,它有责任在其模型和领域模型之间进行转换。

4c) 它们构成了应用层的契约,所以它们是应用层的模型。它们不是域模型的一部分,但它们围绕它形成了一个外观。它们不是拥有自己的 OHS 模型的一部分。

5a) 是的,但如果您调用某个外部 BC,情况总是如此。如果 BC 是本地拥有的,那么您可以就模型(共享内核)达成一些相互协议,但将它们解耦通常仍然更容易。

5b) 是的,但请注意,不需要内部 BC 直接通过 AL 相互呼叫。您仍然有 OHS 选项。

5c) 直接调用BC,绕过应用服务的问题是接口比较复杂,粒度太细。外观模式解释了应用程序服务的好处。这是书中关于粒度的讨论。

于 2013-05-28T18:59:49.013 回答