从产品用例的角度获取图片和评论就像访问数据库一样。唯一的区别是您不查询数据库,而是查询另一个服务。但从您的产品微服务的角度来看,两者都是为您的用例提供数据的外部系统。
当您查看干净的架构时,您会意识到控制器和网关位于同一架构层 - 接口适配器。这一层被命名为“接口适配器”,因为它适配了下层的接口。
如您所见,网关可以是数据库或外部接口(服务)。
因此,您应该以这种方式构建您的应用程序:
+------------------+
| product use case |
+------------------+
|
+------------------+---------------------+
| | |
V V V
+-----------------+ +------------------+ +-------------------+
| ImageRepository | | ReviewRepository | | ProductRepository |
+-----------------+ +------------------+ +-------------------+
^ ^ ^
| | |
===========+=====================+====================+================
| | |
+--------------------+ +--------------------+ +--------------------+
| ImageRestClient | | ReviewRestClient | | JDBCConnector |
+--------------------+ +--------------------+ +--------------------+
您可能想选择其他命名,但结构将保持不变。
易于测试,如果您决定有一天应该在产品微服务中而不是单独的服务中管理图像,您可以将ImageRestClient 替换为JDBCConnector。
编辑
@Rene,请您帮忙理解一下。我经常使用干净的架构,但到目前为止我不明白为什么 DB 层是干净架构中的外圈。是的,它是与外部系统的通信,但是 1)如果 DB 是一个框架,通常主应用程序会导入 DB,反之亦然。
这是依赖倒置原则的一个应用,它告诉我们
“高级策略不应依赖于低级细节。” - Robert. C. Martin
应用程序记住数据的方式是一个细节。我说“记住”,因为这是数据存储的抽象。也许数据存储在数据库中,只是一个文件,甚至只存储在 RAM 中。例如。 Web 应用程序可以使用SessionCartRepository 或DBCartRepository 来存储购物车。
我想人们有时会对干净的架构感到有些困惑,因为他们之前看到的图表将 DB 放在了中心。但是干净的架构图只是一种可视化如何构建应用程序的方式。
几年前我听说过干净的架构,我已经应用了它,但我的图表看起来像这样。
+--------------------+
| ApplicationService | ---+
+--------------------+ |
| | Use Case
======|===================|================
V V Domain
+------------+ +----------------+
| Repository | --> | BusinessObject |
+------------+ +----------------+
^
=======|====================================
| Database
+----------------+
| JdbcRepository |
+----------------+
好的,2014 年我的命名不同了。我的ApplicationService 实现了用例,我的BusinessObject 是CA 的实体。但结构与 CA 提议的相同。当我第一次阅读鲍勃叔叔的书“清洁架构”时,我认为他的图表要好得多。从那时起,我也使用 CA 图。但有时我会使用上面显示的图表,因为有些人喜欢将 DB 层绘制在底部,无论出于何种原因。
- 当外部服务有网络模型并且用例有域模型时,应该由哪一层负责从网络模型映射到域模型(通常对我来说是用例层,但这意味着内层知道外层)。外部服务层是否应该进行映射
在两种类型之间映射的组件必须知道这两种类型,因此它对这两种类型都有依赖关系。
+------------+ +--------+ +------------+
| SourceType | <---- | Mapper | ----> | TargetType |
+------------+ +--------+ +------------+
因此,您不能将映射代码放在实体层或用例层中,因为这些层将依赖于外层,例如网络模型是细节。这将违反干净架构的依赖规则。
因此您必须将映射代码放在外层(例如网络层)。
最后编辑
您提到您的图表有点旧,因为您以前使用过它。那么现在正确的做法是什么?
鲍勃叔叔的做法,因为它是广泛使用的一种,只有他的观点被命名为“清洁架构”。我的没有名字。
如果我现在理解正确 1) 存储库应该只位于外层,并且只有用例可以与存储库对话(当然是通过抽象)?
存储库实现放置在外层。定义,例如接口或抽象类放在用例层。换句话说,用例说明了它需要什么,例如带接口。像数据库这样的提供者实现了它。
- 域层是干净架构中的实体? 3) 或者某些 Repos 应该位于域层并与 DB 层(外层)中的 Repos 对话(所以这意味着 UseCases 不与 DB Repos 对话)
这是我在听说干净架构之前的“旧”观点。我通常将存储库放在用例旁边。我通常也应用接口隔离原则,这意味着我创建了特定于用例的存储库。例如
public interface PlaceOrderRepository {
...
}
在听说 CA 之前,我将存储库定义作为抽象类放在域层中,以便可以使用包修饰符。这是我今天不再做的事情。今天我将工厂放在可以从包范围中受益的实体层(如果我需要包范围)并让存储库使用这些工厂。
因此,我建议在用例用例层定义用例特定的存储库,并在外层 - 接口适配器层实现它们。
我想这就是为什么这个层被称为接口适配器的原因,因为它是你为在内圈中定义的接口实现适配器的层。