Coding style 干净的体系结构-在哪里放置输入验证逻辑?

Coding style 干净的体系结构-在哪里放置输入验证逻辑?,coding-style,business-logic,clean-architecture,Coding Style,Business Logic,Clean Architecture,也许在应用程序中,我有一个功能,允许用户使用带有验证逻辑的表单发送反馈: 名称可以为空 反馈信息应至少包含5个字符 您将把这些验证逻辑放在哪里,或者作为业务逻辑放在域层中,或者作为UI逻辑放在表示层中 这些逻辑适用于所有应用程序(android、iOS、web)。请注意,我们已经进行了服务器端验证。我不是android或ios开发人员,但我在web开发方面有一些经验。一些同事经常问这个问题。对我来说,答案是两者兼而有之 例如,如果在表示层中有验证逻辑,则每当用户发送错误输入时,必须转到服务器

也许在应用程序中,我有一个功能,允许用户使用带有验证逻辑的表单发送反馈:

  • 名称可以为空
  • 反馈信息应至少包含5个字符
您将把这些验证逻辑放在哪里,或者作为业务逻辑放在
域层
中,或者作为UI逻辑放在
表示层


这些逻辑适用于所有应用程序(android、iOS、web)。请注意,我们已经进行了服务器端验证。

我不是android或ios开发人员,但我在web开发方面有一些经验。一些同事经常问这个问题。对我来说,答案是两者兼而有之

例如,如果在表示层中有验证逻辑,则每当用户发送错误输入时,必须转到服务器,进行验证,然后返回错误。为了避免询问服务器,您可以使用html5或javascript验证表示层。如果某些输入不正确,则会显示给用户,并且不会与服务器通信(因此可以避免一个请求)。但是这种验证可以很容易地跳过,因此如果用户更改了某些内容或使用工具(如postman)执行请求,这种验证就不会发生。因此,您无法确定所接收的数据是否正常。为此,您还需要服务器验证

对我来说,这是一个更安全的解决方案,您只使用UI来避免对服务器的错误请求


希望这能有所帮助。

我认为许多开发人员在
展示层,特别是在
视图模型/演示者/控制器中(不是
活动/片段/视图中的)。我的方法是将该逻辑放入
层。为什么?

  • 是表示逻辑还是域逻辑?表示逻辑是由您决定的“映射渲染模型”、“渲染模型的格式”、“如何渲染”、“什么颜色、什么大小、哪个文本”、“它将在屏幕上停留多长时间”等等。。。如果验证是表示逻辑,为什么后端代码具有相同的验证控制?在我看来,验证是域逻辑
  • 为什么验证是域逻辑?谁来决定用户名是否最多为20个字符?商业规则决定一切。谁决定购物篮中最多的物品数量?商业规则决定一切。用户名的长度由业务决定,该规则适用于项目中的任何地方。CreateProfile/UpdateProfile/Register等。。都有相同的max-20char-username规则长度控制(验证)代码应位于域层。
  • 如果验证代码位于域层,那么流程是什么?用户单击视图中的按钮。ViewModel/Presenter调用域层函数。域层函数验证输入数据。如果存在无效的输入参数,则返回带解释的
    ValidationException
    ValidationException
    将包含无效参数的列表、它们失败的验证类型(minLength、maxLength、emailPatternMismatch等)、预期值(最多20个字符等)
    ViewModel/Presenter/Controller
    获取此
    ValidationException
    ,这里有表示逻辑。现在它决定渲染什么,如何渲染。我们是呈现所有无效输入的错误,还是仅呈现第一个无效输入的错误?应显示什么文本/颜色(基于ValidationException中的数据)?我们是否将错误呈现为弹出窗口/文本视图/工具提示?在做出所有演示决策并创建新模型后,
    查看
    就可以了!使用该模型进行渲染
  • 另一点是,在域层中,验证代码应该在哪里?在用例函数或模型(为什么不)本身中?在IMHO中,应该存在具有通用验证逻辑的无状态通用接口/类。在这一点之后,每个用例类都可以实现ValidationInterface或将其作为类对象注入。如果多个用例需要相同的验证,验证控制逻辑将被复制。如果我们将验证逻辑放入模型本身,会发生什么?该模型将实现ValidationInterface(仅具有无状态纯函数!),并具有
    funValidate():ValidationOutcome
    函数。我认为将业务模型的验证逻辑放在其自身并不成问题。所有用例只调用
    model.validate()
    。模型和验证结果之间存在依赖关系
我猜@sufian引用了这句话,这在做出决定时会很有用

指出,正如Clean体系结构将责任按层划分一样,每一层都有自己的验证逻辑

在每一层中,系统应拒绝违反其层职责的输入。因此验证的含义因其上下文而异

在应用层中,作为验证,我们必须确保域对象可以接收输入。我们应该拒绝域对象无法接收的输入


例如,当缺少某些必需参数时,它应该被拒绝,因为域对象无法接收类似于该参数的数据。

同意我们应该始终进行服务器端验证,但我实际上关心的是客户端的验证逻辑,以避免冗余请求,并具有更好的用户体验,用户无需等待api验证,例如,它在打字时也会立即做出反应。是的,我理解你的意思。对我来说,api应该总是同时具有这两种类型。带有验证的用户体验(不涉及服务器)和服务器验证。因为前端或UX发送到服务器的数据不能100%信任。因此,答案是将验证登录名放在server和UX.Insightful中。鲍勃叔叔也说过类似的话解释得很好。ValidationException将重点放在了这里。