Symfony2 Form component - violating MVC and SRP? Symfony2 Form component - violating MVC and SRP? symfony symfony

Symfony2 Form component - violating MVC and SRP?


The problem about form processing is that it violates MVC by definition. This is a problem known as "crosscutting" and has been studied by science in the past. The paper Domain Driven Web Development With WebJinn, for example, is an interesting read about the topic.

As an example, think about the relation of forms to the different layers of MVC:

Model:

  • Forms replicate the informational structure of your domain model (DM). If you change this structure (e.g. by adding fields to a data structure or by adding parameters to a procedure), you must also adapt the forms for entering that information.
  • They need type information from your DM to convert input to the types required there.
  • They need to know the constraints specified in your DM to validate the input.
  • They ideally read and write data directly from/to your DM (e.g. by reading/writing fields of a data structure or by invoking a procedure in the DM with the submitted values as parameters).

Controller:

  • Forms receive submitted data and send it to the DM.
  • They alter the program flow depending on whether they validate successfully or not.

View:

  • Forms render as a complex structure of HTML tags and attributes that depends on all of the above (Should a field be required? Should errors be displayed? How to order the fields? What choices to offer in a drop-down? etc.)

Consequently, it is impossible to write a form abstraction mechanism that does not touch all of these layers. The solution, on the contrary, is to structure the form library itself according to MVC, into different layers and sub-components that fulfill the SRP. If you look into the Symfony2 Form component, it does so pretty well. ;)

So why is it such a "massive scary beast"? The first problem is that of abstraction. Think of a simple drop-down for example. If we want to reuse the code for the drop-down, we need to abstract it somehow. Now check the list above, even this simple input touches all three layers of an MVC application. How can you abstract something that is meant to be structured into three different parts?

The second problem is feature diversity. Form libraries never solve all the problems that developers face in their daily lives. So all these layers and abstraction mechanisms need to be extensible so that you can make them behave exactly like you want them to.

While being extensible, the Form component already solves hundreds of tiny problems that you don't even have to think about anymore. How to input dates, how to select one or many of a list of choices using different UIs (drop-downs, checkboxes, radio buttons, etc.), how to protect forms again security flaws and many more are topics that I could write essays about.

You see that form libraries turn out to be quite complex. The best bet that we have at writing such "massive scary beasts" is to make their API as simple as possible for beginners, as flexible as possible for more advanced users and to write extensive documentation about leveraging its full power. The last point is definitely still lacking (please help!), but we're continually working on all of the above.

Reducing a complex to a simple problem, on the other hand, is unfortunately not possible.

What about other form libraries out there that are so much simpler? In my humble opinion, these don't even try to address a majority of the problems that the Symfony2 Form component already solves for you. :)

Update January 24, 2014: For anybody that wants to know more (much more), here's a paper that I published on the subject.