干净的架构 UseCases 与具有功能的控制器

Posted

技术标签:

【中文标题】干净的架构 UseCases 与具有功能的控制器【英文标题】:Clean architecture UseCases vs Controller with functions 【发布时间】:2019-11-01 09:24:12 【问题描述】:

我刚开始阅读有关干净架构的内容,但对用例实现的定义感到困惑。

考虑一个控制器类,它具有一组接受 T 并在执行某些逻辑后返回 R 的函数

interface IController 
   fun usecase1(param:T) : R 
   fun usecase2(param:T) : R

现在我可以使用 IController 实例执行用例了。

另一种方法是将每个用例定义为一个类并注入其他需要该功能的对象。

class UseCase1 
    fun execute(param:T):R 


class UseCase2 
    fun execute(param:T):R 

将用例作为单独的单元与将其作为某个类的函数之间有什么优点/缺点?

国际海事组织, 单独的单元增加了构造和注入开销 而其他方法则存在“组合继承问题”。哪条路是正确的?

【问题讨论】:

【参考方案1】:

根据接口隔离原则,最好为每个用例有单独的用例接口。它允许您以某种方式抽象用例实现。您可以独立于控制器层拆分或划分用例的实现。

我恭敬地建议将每个用例拆分为单独的类。因为当您修改其中一个时,您将 100% 确定您不会制动另一个。 但是如果你有很多用例,而且它们很小,那么在这种情况下,将它分组到文件中是有意义的。但我认为高阶函数比类中的一堆函数更适合。

创建具有状态和行为的类是有意义的,但是如果您为用例创建类,它将是无状态的,并且方法几乎不会密切相关。

但真正重要的是,根据干净的架构,它是分离层。如何组织存储用例并不重要,但以后有可能独立于其他层来改变决策是非常重要的。

【讨论】:

【参考方案2】:

将用例作为单独的单元与将其作为某个类的函数之间有什么优点/缺点?

如果你把所有东西都放在控制器中,你将违反单一责任原则。控制器代码与用例代码的更改原因不同。

例如控制器通常在演示者的帮助下从用户那里获取输入并为用户创建输出。这意味着它从视图模型中读取输入并更新视图模型。视图模型属于 UI,会因为 UI 原因而改变。

如果您正在实施干净的架构,则用例不得依赖于 UI,它们会因与 UI 不同的原因而发生变化。用例与 UI 无关。这也将使它们更易于测试,并且可以更轻松地与其他 UI 一起使用。

考虑一个控制器类,它具有一组接受 T 并在执行某些逻辑后返回 R 的函数

请记住,控制器的参数和返回类型与用例的类型不同。

您的控制器可能会使用为 json 序列化和反序列化而设计的类型。那是运输问题。用例不关心传输。数据传输的方式是一个细节。网络是一个细节。如果您对控制器和用例使用相同的类型,您将在它们之间创建依赖关系。

【讨论】:

【参考方案3】:

Clean Architecture 是其层之间耦合较少的一种。现在,当我们尝试在像 Google Photos 这样的网络应用程序上应用干净的架构时,它可能有几个层,例如,

    UI 层(用户感知的那一层) 路由层,可以将 URL 路由到正确的类文件 根据用例可能有多个适配器层

    可以再次细分的持久层,

    4.1。元数据持久性(例如;Postgress、mysql

    4.2。内容持久性(例如 Hadoop)

如何在这里展示用例?

用例是描述系统上的用户交互的用例。这可以像在身份验证期间验证错误密码一样简单(或)提供对图片应用过滤器的选项。实现一个用例可以在一个方法中结束,也可以在多个类和文件之间产生。

清洁架构是一种指导方针,它坚持我们在层之间保持松散耦合,以便用极少的更改轻松替换一个层。

【讨论】:

以上是关于干净的架构 UseCases 与具有功能的控制器的主要内容,如果未能解决你的问题,请参考以下文章

清洁架构用例/领域层的相关性

智能风控决策引擎系统架构设计与开发实践

干货第三方支付风控系统架构与运作机制阐述

步进指令与顺控程序设计

车路云一体化融合控制系统

车路云一体化融合控制系统白皮书