Validation 选择将验证放在何处?

Validation 选择将验证放在何处?,validation,hanami,Validation,Hanami,请考虑以下代码段: 注意标题和作者上的验证,它们位于控制器操作中。我的问题是:为什么这些验证是在操作参数上,而不是在书实体上?也就是说,假设验证在Book上,您可以编写如下内容: def call(params) book = Book.new(params) if book.valid? @book = BookRepository.create(Book.new(params[:book])) redirect_to '/books' end end 只需完全

请考虑以下代码段:

注意
标题
作者
上的验证,它们位于控制器操作中。我的问题是:为什么这些验证是在操作参数上,而不是在
实体上?也就是说,假设验证在
Book
上,您可以编写如下内容:

def call(params)
  book = Book.new(params)
  if book.valid?
    @book = BookRepository.create(Book.new(params[:book]))

    redirect_to '/books'
  end
end
只需完全去掉
params
块。这对我来说似乎更自然,并将促进在不同操作之间更容易地重复使用验证

params
方法是否有我没有看到的优点?将验证放在
书籍
实体上是否有缺点?

官方指南中的部分解释了为什么应该对请求进行验证,而不是对模型进行验证

概括起来,有两个主要原因:

  • 从体系结构的角度来看,不应允许无效输入进入系统,因此最好在控制器级别完全跳过这些输入,而不是仅仅为了验证而创建模型,因为这是一个非常昂贵的操作

  • 可能有多个请求在同一个模型上工作。如果在模型级别进行验证,还需要考虑这些请求的不同场景,这同样是控制器的责任,而不是模型的责任


  • 尽管如此,如果你能在你的业务逻辑中处理上述场景,那将归结为个人偏好问题。

    自从发布这篇文章以来,我已经阅读了更多关于这个主题的内容,以及你在第2部分中的观点。这确实是将验证排除在实体之外的关键原因。然而,在我看来,将它们付诸行动仍然是错误的,因为这将它们与交付机制联系起来。我很感谢你的反馈,我在这里详细阐述了这一点。
    def call(params)
      book = Book.new(params)
      if book.valid?
        @book = BookRepository.create(Book.new(params[:book]))
    
        redirect_to '/books'
      end
    end