干净的体系结构:为什么不使用实体作为用例(交互器)的请求模型

时间:2018-10-15 08:12:13

标签: oop web-applications architecture clean-architecture

我已经阅读了PPP书以及干净的代码,编码器和体系结构书。

我知道:

  • 清洁架构是分层架构
  • 开放层或封闭层架构是什么感觉
  • 干净的建筑书籍建议,每个层都可以访问其内部层,而不仅是下一个内部层。

因此,我假设干净的体系结构不会强制分层,而是允许分层,这意味着例如位于框架层的UI可以直接访问Entity,从而跳过2层。

我了解,如果强制将干净的体系结构紧密地分层,我们将无法直接从Frameworks层实现存储库接口,而应在下一层的条件下实现它,而下一层应该在下一层的条件下实现它层等等。

现在我的问题是,为什么我们不能直接引入Entity作为用例或控制器的参数类型,为什么我们必须在中间层中定义数据结构或DTO并烦扰将实体转换为数据结构并返回它作为响应,同时允许我们使用控制器层中的Entity,因为未违反访问规则?

考虑这个例子,假设我们有:

  • JobView
  • JobController
  • JobUseCase(RequestModel) : ResponseModel
  • JobEntity

现在,如果JobView要呼叫JobController,它将通过RequestModel。现在我们可以像这样简单地将JobEntity引入为RequestModel了吗:

  • JobView
  • JobController
  • JobUseCase(JobEntity)
  • JobEntity

我知道这样做会增加代码的脆弱性,因为这样一来,如果我们更改JobEntity,那么JobView就必须更改。但是干净的体系结构是否会强制SOLID原则变得脆弱或僵化?!

4 个答案:

答案 0 :(得分:4)

不确定我是否理解您的问题背后的原因:

  

干净的体系结构是否会强制采用SOLID原则,或者通常不是脆弱或僵化?

清洁建筑如何可能会强加刚性和脆弱性?定义体系结构的全部内容是:如何广泛地照顾基本的OOP原则,例如SOLID和其他

另一方面,您的以下示例肯定会使清洁架构变性:

  

JobView > JobController > JobUseCase(JobEntity) > JobEntity

这隐含地告诉我们,您最有可能从控制器中检索了实体,这完全错过了 Interactor (或用例)以及 Clean Architecture < / em>。

Interactors 封装应用程序业务规则,例如与 interactions 与实体的交互以及通过 Entity Gateway 完成的对实体的CRUD,进而封装基础结构层

此外,在清洁架构上下文中,作为模型层一部分的实体应该与作为交付机制一部分的控制器(或更确切地说,是评估者)无关HTTP请求消息。以这种方式使作为控制器的较低级别组件变性会对SRP( =>脆弱性增加)和组件之间的去耦程度( =>刚性增加)产生负面影响

最后,你说:

  

而且我了解到,如果干净的体系结构被迫紧密地分层,那么我们将无法直接从Frameworks层实现存储库接口,而应该在下一层中实现它,而下一层应该在下一层中实现它的下一层等等。

您的实体框架的RepositoryInterface及其实现属于基础结构层,应进行包装,并由实体网关进行修改。


其他资源

enter image description here

答案 1 :(得分:2)

上面的答案是正确的,但是我想指出为什么这会造成混乱,就像我以前看到的那样:因为从依赖关系的角度来看,跨边界传递实体没有任何错误。您不能传递的是依赖于外层的任何类型,出于显而易见的原因,这是不可以的。这本书中有很多是关于依赖性问题的,所以引起了混乱-为什么实体不好?

如上所述,实体需要像其他任何代码一样遵守SRP。如果使用实体进行数据传输,则引入了不必要的耦合。当实体出于业务原因需要更改时,至少需要更改映射代码,甚至可能在外层更改,以响应。

答案 2 :(得分:1)

为什么不将实体用作用例的请求模型?

您已经亲自回答了这个问题:即使您没有违反依赖关系规则,也会增加代码的脆弱性。

为什么我们不能直接将Entity作为用例或控制器的参数类型,以及为什么我们必须在中间层定义数据结构或DTO并烦扰将实体转换为数据结构并将其作为response返回,所以是否允许访问并在Controller层中查看Entity,因为没有违反访问规则?

(关键业务)实体和DTO在应用中的原因非常不同。实体应该包含关键的业务规则,并且与适配器和交互器之间的通信无关。应该以最方便的方式来实现DTO,以增强这种沟通,并且没有任何直接的理由依赖业务实体。

即使一个实体可能具有与DTO完全相同的代码,这也应被视为巧合,因为它们更改的原因完全不同(单一责任原则)。这似乎与流行的DRY原理相冲突(请不要重复说明),但是DRY声明不应重复知识,只要在应用程序的不同部分,代码可能仍然相同因不同原因而改变。

答案 3 :(得分:0)

这个图中箭头方向的重要之处,都指向更高层。应用依赖倒置原则,允许高层不依赖低层,并通过接口正好相反。

另外,回答@HandOfDoom:根据实体制作外层是错误的,外层不需要知道实体暴露的所有内容,它只对某些表示特定的数据感兴趣,用例使用实体层为它们明确收集。 所以不,当您在控制器、演示者或视图中时,不要依赖实体,永远不要。你会知道的太多,远远超出你的需求,并且会变得依赖一些你甚至不需要的东西(方法,...),并且在这些实体中被修改的情况下会自动且无用地受到影响。