首页 > web前端 > js教程 > 针对表单对象的案例

针对表单对象的案例

DDD
发布: 2025-01-17 00:31:13
原创
115 人浏览过

A case against form objects

注意:虽然本讨论使用 Ruby on Rails 示例,但核心概念广泛适用于其他语言和框架。

表单对象的问题:批判性检查

让我们澄清一下 Web 应用程序开发中经常模糊的“表单对象”概念。 根据各种文章(下面链接)和实践经验,表单对象缺乏普遍认可的定义和目的。 他们的角色经常被描述为:

  • 数据验证: 验证用户输入的简单 Ruby 对象。
  • 模型聚合:代表来自多个模型的数据的虚拟模型。
  • 强参数替换:用于输入清理的强参数的替代方案。
  • 回调重构:一种重新组织模型生命周期回调的方法。
  • form_for 助手: 专门设计用于 Rails 的 form_for 助手的对象。

主要目标通常被认为是通过处理参数处理、类型强制和基本验证来简化控制器。 它们还用于封装来自单个表单提交的多个 ActiveRecord 模型的更新,模仿 ActiveRecord 行为以提高控制器的熟悉度。 它们被视为管理复杂行为的一种方式。

为什么使用表单对象?预期好处:

据称的优点包括:

  • 解耦:将业务逻辑与控制器和模型分离。
  • 查看帮助器:为复杂表单元素提供帮助器方法(例如,选择字段的选项)。
  • Rails 约定遵守: 简化复杂表单,不直接映射到单个 ActiveRecord 模型。

然而,缺乏明确的定义导致了第一个主要问题:沟通不畅。当在代码库中遇到表单对象时,不清楚它们履行哪些角色(或其组合)。

本质上,表单对象旨在通过集中职责(通常在模型和/或控制器层内)来重构代码复杂性。 但这导致了第二个问题:意外的膨胀

缺点:“胖形式对象”反模式

考虑一个常见的实现:

<code class="language-ruby">class SomethingController
  def create
    @form = MyForm.new(action_params)
    if @form.valid?
      @form.save!
      redirect_to "somewhere"
    else
      render :new
    end
  end
  def new
    @form = MyForm.new
  end
end</code>
登录后复制
登录后复制

这种看似简单的方法掩盖了一个重大问题。 表单对象的公共 API(newvalid?save! 及其在视图中的存在)显示它处理:

  • 参数解析:理解并转换请求参数。
  • 验证:了解参数类型和验证规则(业务逻辑)。
  • 持久化:了解如何创建和持久化数据(与数据库交互)。
  • 视图逻辑: 可能包含与视图相关的逻辑(表单元素的辅助方法)。

这违反了单一责任原则。 表单对象成为各种关注点的存储库,随着时间的推移吸引更多的责任(额外的视图助手、验证规则等)。 它演变成一个“胖形式的对象”,反映了它想要解决的问题。

第三个问题:冗余

更重要的问题是这些职责通常已经由其他组件处理:

  • 坚持:这是模特的责任。 委托给模型而不是复制其功能。
  • 业务逻辑:使用服务对象来实现复杂的业务逻辑。
  • 输入验证: 使用验证库(ActiveRecord::Model、Scrivener、dry-schema)。
  • 视图助手:使用视图模型或演示者。

在中型到大型应用程序中,这些组件可能已经存在。引入具有重叠职责的表单对象会增加不必要的复杂性和架构模糊性。 复杂性应该被直接解决,而不是被掩盖。

提议的替代方案:更加模块化的方法

更结构化的方法为每个职责使用专用对象:

<code class="language-ruby">class SomethingController
  def create
    @form = MyForm.new(action_params)
    if @form.valid?
      @form.save!
      redirect_to "somewhere"
    else
      render :new
    end
  end
  def new
    @form = MyForm.new
  end
end</code>
登录后复制
登录后复制

这种方法的优点:

  • 明确的职责:每个对象都有一个明确的单一目的。
  • 可测试性:更容易、更快速地测试各个组件。
  • 可维护性:改进的代码结构和可维护性。

结论:

表单对象本质上并不是坏事。如果明智地使用它们,它们会是有益的。 然而,它们的模糊定义和责任膨胀的倾向值得仔细考虑。 在引入或使用表单对象之前,请考虑现有组件是否已经处理所需的功能。 如果存在复杂性,请通过定义良好、单一用途的对象来拥抱它,而不是将其隐藏在定义不明确的“表单对象”中。

链接文章(为清晰起见重新格式化):

  • 重构 Fat ActiveRecord 模型的 7 种模式
  • 纪律轨道:形成对象技术和模式 - 第 1 部分
  • 基本 RubyOnRails 模式 — 第 4 部分:表单对象
  • ActiveModel 表单对象
  • 如何使用表单对象保持控制器精简
  • 在 Ruby on Rails 中使用表单对象
  • 验证表单对象
  • 使用 ActiveModel 创建表单对象
  • 使用表单对象重构您的代码

以上是针对表单对象的案例的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板