干净的架构——在哪里放置输入验证逻辑? [关闭]
Posted
技术标签:
【中文标题】干净的架构——在哪里放置输入验证逻辑? [关闭]【英文标题】:Clean architecture - where to put input validation logic? [closed] 【发布时间】:2019-12-27 10:17:40 【问题描述】:也许在应用程序中我有一个功能,允许用户使用带有一些验证逻辑的表单发送反馈:
名称可以为空 反馈信息至少应包含 5 个字符您会将这些验证逻辑放在哪里,要么作为业务逻辑放在 domain layer
中,要么作为 UI 逻辑放在 presentation layer
中?
这些逻辑适用于所有应用程序(android、ios、web)。请注意,我们已经进行了服务器端验证。
【问题讨论】:
【参考方案1】:我猜这个@sufian 引用的example of Uncle Bob 和这个article 在做出这个决定时会很有用。
Naoto 指出,正如 Clean Architecture 按层划分职责一样,每一层都有自己的验证逻辑。
在每一层中,系统应该拒绝违反其层职责的输入。因此验证的含义根据其上下文而有所不同。
在应用层中,作为验证,我们必须确保域对象可以接收输入。我们应该拒绝域对象无法接收的输入。
例如,当缺少某些强制参数时,应该拒绝它,因为域对象无法接收这样的参数。
【讨论】:
【参考方案2】:我认为许多开发人员在Presentation
层中这样做,特别是在ViewModel/Presenter/Controller
中(不是在Activity/Fragment/View!
中)。我的方法是将这个逻辑放在Domain
层中。为什么?
ValidationException
并说明。 ValidationException
将包含无效参数列表、验证类型它们失败(minLength、maxLength、emailPatternMismatch 等),这是预期的(最多 20 个字符等。)。 ViewModel/Presenter/Controller
得到这个 ValidationException
,这里我们有 演示逻辑。现在它决定渲染什么,如何渲染。我们是渲染所有无效输入的错误还是只渲染第一个无效输入?应该显示什么文本/颜色(基于 ValidationException 中的数据)?我们是否将错误呈现为弹出/文本视图/工具提示?在做出所有演示决定并创建新模型之后,View
就可以了!使用该模型进行渲染。
还有一点是,在域层,验证码应该放在哪里?在 UseCase 函数或模型(为什么不)本身中?恕我直言,应该有具有通用验证逻辑的无状态通用接口/类。在那之后,每个 UseCase 类都可以实现 ValidationInterface 或将其作为 Class 对象注入。如果多个 UseCases 需要相同的验证,验证控制逻辑将被复制。如果我们将验证逻辑放入模型本身会发生什么?模型将实现 ValidationInterface(仅具有无状态纯函数!)并具有 fun validate():ValidationOutcome
函数。我不认为将业务模型的验证逻辑放在自身中是有问题的。所有用例都只会调用model.validate()
。 Model 和 ValidationOutcome 之间存在依赖关系。
【讨论】:
有见地。 Bob 叔叔在one of the threads 中也说过类似的话。 :) 很好解释。 ValidationException 让我们明白了这一点。 来自 Bob 叔叔的评论 @Sufian 提到,在 Clean Arch 的上下文中,每一层都可以/应该有自己的验证。所以我认为将验证放在域层中会验证域而不是演示者或实体。例如,客户评论长度不应超过 100 个字符,但管理员最多可以回答 1000 个字符。就像在干净的架构中一样,我们不应该改变内层,通过改变外层,似乎这里我们需要在表示层中进行验证。【参考方案3】:我不是 android 也不是 ios 开发人员,但我在 web 开发方面有一些经验。一些同事经常问这个问题。对我来说,答案是两者兼而有之。
例如,如果您在表示层中有验证逻辑,则每当用户发送错误的输入时,您必须转到服务器,验证然后返回错误。为了避免询问服务器,您可以使用 html5 或 javascript 验证表示层。如果某些输入是错误的,则会向用户显示,并且与服务器没有通信(因此您避免了一个请求)。但是这个验证可以很容易地跳过,所以如果用户改变了一些东西或者用一个工具(比如邮递员)做请求,这个验证就不会发生。因此,您无法确定您收到的数据是否正常。为此,您也需要服务器验证。
对我来说,这是更安全的解决方案,您只使用 UI 来避免对服务器的错误请求。
希望这会有所帮助。
【讨论】:
同意我们应该始终进行服务器端验证,但我真正关心的是客户端的验证逻辑,以避免冗余请求并获得更好的用户体验,用户无需等待 api 验证,例如,它也会在打字时立即做出反应。 是的,我理解你。对我来说,一个 api 应该总是有两种类型。带有验证(不涉及服务器)和服务器验证的 UX。因为您不应该 100% 信任前端或 UX 发送到您的服务器的数据。所以答案是将验证登录放在服务器和用户体验中。以上是关于干净的架构——在哪里放置输入验证逻辑? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
在 DDD 架构中,我应该将与按角色用户过滤数据相关的查询逻辑放在哪里