Mas*_*aBa 3 architecture oop web-applications clean-architecture
我已经阅读了PPP书以及干净的代码,编码器和体系结构书。
我知道:
因此,我假设干净的体系结构不会强制分层,而是允许分层,这意味着例如位于框架层的UI可以直接访问Entity,从而跳过2层。
而且我了解到,如果强制将干净的体系结构紧密地分层,我们将无法直接从Frameworks层实现存储库接口,而应该在下一层实现它,而下一层应该在下一层实现它,因此上。
现在我的问题是,为什么我们不能直接引入Entity用例或控制器的参数类型,为什么我们必须在中间层定义数据结构或DTO并烦扰将实体转换为数据结构并将其作为响应返回,而我们被允许使用并Entity在控制器层中查看,因为未违反访问规则?
考虑这个例子,假设我们有:
JobViewJobControllerJobUseCase(RequestModel) : ResponseModelJobEntity现在如果JobView要打电话JobController,应该通过RequestModel。现在我们可以像这样简单地介绍JobEntity一下RequestModel:
JobViewJobControllerJobUseCase(JobEntity)JobEntity我知道这样做会增加代码的脆弱性,因为如果我们更改JobEntity,则JobView必须更改。但是,干净的体系结构是否会强制SOLID原则变得脆弱或僵化?
小智 10
为什么不使用实体作为用例的请求模型?
你自己已经回答了这个问题:即使你没有打破依赖规则,它也会增加代码的脆弱性。
为什么我们不能直接引入 Entity 作为用例或控制器的 Parameter 类型,为什么我们必须在中间层定义数据结构或 DTO 并将实体转换为数据结构并将其作为响应返回,而我们被允许使用和查看 Entity在控制器层,因为没有违反访问规则?
(关键业务)实体和 DTO 的应用原因非常不同。实体应包含关键业务规则,与适配器和交互器之间的通信无关。DTO 应该以最方便的方式实施以增强这种沟通,并且没有任何直接的理由依赖于业务实体。
即使实体可能具有与 DTO 完全相同的代码,这也应该被视为巧合,因为它们更改的原因完全不同(单一责任原则)。这似乎与流行的 DRY 原则相冲突(不要重复自己),但 DRY 指出知识不应重复,只要因不同原因更改代码,应用程序的不同部分可能仍然看起来相同。
不知道我能理解您问题背后的原因:
干净的体系结构是否会强制执行SOLID原则,或者通常不会变得脆弱或僵化?
清洁建筑可能如何迫使刚性和脆弱性?定义体系结构的全部意义在于:如何广泛照顾SOLID等OOP基本原则 ……
另一方面,您的以下示例肯定会使Clean Architecture变性:
JobView>JobController>JobUseCase(JobEntity)>JobEntity
这隐含地告诉我们,您最有可能从控制器中检索了您的实体,这完全错过了Interactor(或用例)以及Clean Architecture的意义。
交互器封装了应用程序业务规则,例如与实体的交互以及通过实体网关完成的实体上的CRUD 交互,而实体网关又封装了基础结构层。
此外,在“ 干净架构”上下文中,属于模型层的实体应该与作为传递机制一部分的控制器(或更确切地说,是HTTP请求消息的评估者)无关。以这种方式使作为控制器的较低级别的组件变性将对SRP(=>脆弱性增加)和组件之间的去耦程度(=>刚性增加)产生负面影响。
你说:
而且我了解到,如果强制将干净的体系结构紧密地分层,我们将无法直接从Frameworks层实现存储库接口,而应该在下一层实现它,而下一层应该在下一层实现它,因此上。
您的实体框架RepositoryInterface及其实现属于基础结构层,因此应该对其进行包装,并由实体网关进行调整。当我们在谈论基础架构的封闭层的port()的实现时,这里要遵守的Demeter法则可能很重要EntityGatewayInterface。
最后,我怀疑以下假设是错误的,因此所有基于该假设的进一步假设也会因此而陷入混乱:
因此,我假设干净的体系结构不会强制分层,而是允许分层,这意味着例如位于框架层的UI可以直接访问Entity,从而跳过2层。
但是,无论是否强制分层,Clean Architecture都明确且具体地定义了自己(组件之间的关系),例如在以下UML类图中:
从该图中我只能看到一个紧密分层的体系结构……
在我看来,开放层是一种含氧化合物,它并不约束该层应受自然约束的东西,因为根据定义,一层是隔离的,是一组简化为其端口的组件的抽象,意味着减少诸如脆弱性等的技术债务...
小智 5
上面的答案是准确的,但我想指出为什么这会造成混乱,正如我之前所看到的那样:因为从依赖关系的角度来看,跨越边界传递实体没有任何问题。您不能传递的是任何依赖于外层的类型,出于显而易见的原因,这是不允许的。书中的大部分内容都讨论了依赖性问题,因此这会造成混乱 - 为什么实体不正常?
如上所述,实体需要像任何其他代码一样遵守 SRP。如果您将实体用于数据传输目的,则引入了不必要的耦合。当实体因业务原因需要更改时,至少映射代码以及外层中的更多代码需要响应更改。