Symfony2表单组件 - 违反MVC和SRP?

时间:2013-04-02 10:28:19

标签: php model-view-controller design-patterns symfony single-responsibility-principle

我使用Symfony2的次数越多,与形式的斗争就越多,我得出的结论是,它们是一种巨大的可怕的野兽,甚至不应该存在。

我发现了这篇文章here,我发现我同意作者的观点。即使该文章是针对Symfony 1.x,我认为它仍然适用于Symfony2中的Form组件。看起来表单组件似乎试图在一个地方解决属于模板,控制器和模型的问题。这不是严重违反MVC和/或SRP(单一责任原则)吗?

这可能是一个不同的问题,但我觉得它有点相关 - 我也注意到symfony的很多可用包试图解决视图外的视图问题,例如:

KnpMenuBundle - 您在服务器端使用oo接口生成菜单(为什么不在它们所属的视图层中?)

IvoryCKEditorBundle - 将textarea转换为ckeditor是在视图文件的一个jquery行中完成的,那么为什么这个包存在呢?我甚至不想计算那里的行数。

所以在Symfony的核心区域似乎有这些违规行为,或者我只是没有得到它?

1 个答案:

答案 0 :(得分:21)

表单处理的问题在于它违反了MVC的定义。这是一个被称为“横切”的问题,并且过去已经通过科学进行了研究。例如,论文Domain Driven Web Development With WebJinn是关于该主题的有趣读物。

作为一个例子,考虑一下表单与MVC不同层的关系:

<强>型号:

  • 表单复制域模型(DM)的信息结构。如果更改此结构(例如,通过向数据结构添加字段或向过程添加参数),则还必须调整表单以输入该信息。
  • 他们需要来自您的DM的类型信息,以便将输入转换为所需的类型。
  • 他们需要知道DM中指定的约束以验证输入。
  • 理想情况下,它们直接从/向DM读取和写入数据(例如,通过读取/写入数据结构的字段或通过调用DM中的过程并将提交的值作为参数)。

<强>控制器:

  • 表单接收提交的数据并将其发送给DM。
  • 他们会改变程序流程,具体取决于他们是否成功验证。

查看:

  • 表单呈现为HTML标记和属性的复杂结构,取决于以上所有内容(是否需要字段?是否应显示错误?如何排序字段?在下拉列表中提供哪些选项?等。)

因此,不可能编写一个不触及所有这些层的表单抽象机制。相反,解决方案是根据MVC将表单库本身构建到实现SRP的不同层和子组件中。如果您查看Symfony2 Form组件,它会很好。 ;)

那为什么它是一个“巨大的可怕的野兽”?第一个问题是抽象问题。想象一下简单的下拉菜单。如果我们想重用下拉代码,我们需要以某种方式对其进行抽象。现在查看上面的列表,即使这个简单的输入也会触及MVC应用程序的所有三个层。你怎么能抽象出结构化为三个不同部分的东西呢?

第二个问题是特征多样性。表单库从未解决开发人员在日常生活中遇到的所有问题。因此,所有这些层和抽象机制都需要是可扩展的,这样您就可以使它们的行为完全符合您的要求。

虽然可扩展,但Form组件已经解决了数百个您甚至不必考虑的微小问题。如何输入日期,如何使用不同的UI(下拉菜单,复选框,单选按钮等)选择一个或多个选项列表,如何再次保护表单安全漏洞以及更多我可以撰写论文的主题约。

您看到表单库变得非常复杂。我们编写这种“大型可怕的野兽”的最佳选择是让初学者的API尽可能简单,尽可能灵活地为更高级的用户提供,并撰写有关利用其全部功能的大量文档。最后一点肯定仍然缺乏(please help!),但我们一直在努力完成上述所有工作。

另一方面,遗憾的是不可能将复杂问题简化为简单的问题。

那里的其他表单库怎么这么简单呢?在我看来,这些甚至没有试图解决Symfony2 Form组件已经为您解决的大多数问题。 :)

2014年1月24日更新:对于任何想要了解更多内容的人(更多),这里是a paper that I published on the subject