Archive for the 'documentation' Category

The Good, The Bad and the Ugly

There is a lot to learn from Fabien Potencier, the creator of the symfony framework. He often comments people's work on other frameworks, but almost never when someone works on his own framework. So his recent reaction about my DDD experiment is rare enough to be thoroughly analyzed, and distilled. Let's look for the very substance of his latest post.

The Good

It's been more than ten months since my original Forms post, about which Fabien basically told me that I knew nothing about programming (which is true) but nothing else. So I'm very glad that he finally decided to give more feedback about the ideas I suggest. My previous post asked for developers' thoughts about a reworked Chapter 10, and who could better do this than him?

Not only does Fabien talk about my DDD experiment, he actually implemented some features I suggested. Thanks to commits made to the symfony 1.2 branch early this week, building a form object using the sfForm class alone is easier. Added is the ability to define default values for each widget, the ability to iterate on a form object, the ability to directly set a widget or a validator from the from object. I proposed all those changes to make the documentation easier to read (and write), and it seems that they also have an interest for the developers.

Fabien points some mistakes I did, like the 'multiple' validator, which is a bad idea. Since there are two kinds of multiple validators (on the uncleaned value and on the cleaned value), the 'multiple' keyword is not the best choice. I still thing that 'pre' and 'post' validators could get a better name, but that's a detail.

Also, the modified version of my proposed Chapter 10, published as an attachment to Fabien's post, keeps about 90% of the original text unchanged. It seems that he disagrees mostly on some technical details, and didn't touch the order in which things were introduced, nor the length of the Chapter.

The Bad

But the idea to define form widgets and validators based on an associative array got no credit to his eyes. It is probably a matter of preference; I introduced this array syntax for two reasons:

  • To avoid introducing too many classes too early in the documentation
  • To make the YAML form definition syntax completely natural

To my eyes, this array syntax has always been a layer on top of the existing syntax; that means that the ability to define custom widgets and validators is still there, and the ability to pass an object instead of an associative array is still there as well. That's how I tried to remove the coding style preference problem: whatever you like more, symfony supports it. You get both simplicity of use and power.

"[The suggested API] is not shorter, it is not easier to understand, and it is more difficult to explain.". Let me respectfully disagree. It is shorter, easier to understand, and easier to explain. Compare what a single chapter explains and the confusion introduced by an unfinished and lengthy book. Or better, compare:

// in PHP
<?php
class ContactForm extends sfForm
{
  protected static $subjects = array('Subject A', 'Subject B', 'Subject C');
 
  public function configure()
  {
    $this->widgetSchema->setNameFormat('contact[%s]');
    $this->widgetSchema->setIdFormat('my_form_%s');
    $this->setWidgets(array(
      'name'    => new sfWidgetFormInput(),
      'email'   => new sfWidgetFormInput(),
      'subject' => new sfWidgetFormSelect(array('choices' => self::$subjects)),
      'message' => new sfWidgetFormTextarea(),
      'file'    => new sfWidgetFormInputFile(),
    ));
 
    $this->setValidators(array(
      'name'    => new sfValidatorString(array('required' => false)),
      'email'   => new sfValidatorEmail(),
      'subject' => new sfValidatorChoice(array('choices' => array_keys(self::$subjects))),
      'message' => new sfValidatorString(array('min_length' => 4), array('min_length' => 'Your message is too short')),
      'file'    => new sfValidatorFile(),
    ));
    $this->setDefault('email', 'me@example.com');
  }
}
?>


And:

# in YAML
&subjects:     [Subject A, Subject B, Subject C]
name_format:  contact[%s]
id_format:    my_form_%s
widgets:
  name:       text
  email:      { type: text, default: me@example.com }
  subject:    { type: select, choices: *subjects }
  message:    textarea
  file:       file
validators:
  name:       { type: string, required: false }
  email:      email
  subject:    { type: choice, choices: *subjects }
  message:    { type: string, min_length: 4, errors: { min_length: Your message is too short } }
  file:       file

According to Fabien, using associative arrays to make the YAML syntax easier to explain is of no use, since YAML is bad and shall be dropped altogether. "Learn from our mistakes" means that symfony should never had used YAML in the first place, despite the fact that it appealed numerous users to it and that it's only a simplicity layer. That means that the symfony 1.2 admin generator will not be controlled from a YAML file at all - defining form widgets in YAML is an indispensable brick to a YAML syntax for an administration interface. So be prepared to use XML or plain PHP for your database schemas, configuration files, generated modules, etc.

"Learn from our mistakes" also means not using strings to define HTML attributes anymore. I suggested to keep on using the abilities of symfony 1.0 to output clean XHTML attributes from a string looking like 'id=contact_subject class=bar'. But that is something else you should forget about. Apparently, this brings no benefit over array('id' => 'contact_subject', 'class' => 'bar'). Once again, I can understand it's a matter of preference, but I'm convinced that this kind of syntactic sugar is what appealed many users to symfony in the first place.

In the documentation I wrote, I introduced a way to bind a form object to the request object ($form->bind($request)). I explained later in the chapter why it's better to do otherwise, but at least it shows that a form can be used without necessarily using the array syntax for widget names. Fabien explains why this is wrong (as I did) and fails to see the interest of introducing the setNameFormat() in the documentation only when it becomes necessary. However, the current symfony book uses this technique several times (think of in Chapter 2 for instance), because it is easier to know why a practice is wrong once you've seen the advantages of the good practice in comparison. His revised version of the Chapter 10 doesn't solve the problem, either.

But honestly, I don't care much about all these points. If if was just for Fabien's remarks on the technical side of things, I'd be more than willing to continue working on a modified Chapter 10 to make it worthy of The Guide.

The Ugly

But Fabien is really going to a nasty place with his post.

Does he bring a response to my request for comment? No, he replies to a commenter of my post, who challenged him to give his opinion. He never actually addresses me directly - I'm a persona non grata.

Does he agree on the DDD experiment? Of course not, DDD is the "Biggest problem" according to him (not sure why). How could documentation and teaching influence a developer's design decisions? The forms API is "good enough" as is, and its lack of documentation is not a problem to be solved by modifying the code. If someone (but not me) wants to write something to "help us improve the current documentation", he can still try again.

Is he grateful that I did in a week a work (Chapter 10) that he couldn't do in a year? Not at all. Not a word of thanks, he just feels insulted that someone dared to question parts of his work. What a childish reaction to someone who offers to help widen the symfony adoption.

Does he react in the interest of the community, proposing to use his own version of the Chapter 10 for the current guide? Not even that. He prefers no documentation at all rather than an equivalent to the symfony 1.0 documentation updated for symfony 1.1.

Does he care about the newcomers to symfony, those who don't know the 1.0 API by heart, don't follow the Trac timeline every day, don't read the framework code, and don't accept an UPGRADE text file for a documentation? No. Not a word about them in his post. Only the developers who already know good practices of web development can start using symfony. You can no longer learn these practices by learning symfony.

Does he write that he's been implementing some of my ideas? No, that would be giving me too much credit. The goal, here, is to show that I am a bad developer, and nothing else. Well, I'm not even a developer, so why all the hate?

Is he trying to be constructive? No. He writes, in bad faith: "[Francois'] API is so unintuitive that we must explain a lot of things to describe the way it works". God, I thought that I managed to explain in 1 hour what he needs a day to teach in an expensive training, and it's my API that is unintuitive?

Conclusion

All in all, Fabien reacts with pride rather than reason. He does as much as he can do discredit my work, while my purpose has always been to help leverage the symfony adoption. He probably dreams that, with a single blog post, I'd leave the symfony community completely, because he finally demonstrated that none of my work is worthy to his eyes.

Too bad, Fabien, you have taken the wrong path. I'll be a pain in your ass for a long time. Count me in to constantly remind people that symfony is a one-man work, and that this is a very high risk for enterprise projects, given the man.

Chapter 10 - Forms

Dealing with the display of form inputs, the validation of a form submission, and all the particular cases of forms is one of the most complex tasks in web development. Luckily, symfony provides a simple interface to a very powerful form sub-framework, and helps you to design and handle forms of any level of complexity in just a few lines of code.

NOTICE: This document is the first draft of a methodology experiment explained earlier in this blog. It documents the sfForm framework found in symfony 1.1, but with some changes in the API and usage. As such, it describes a library that is not yet written (like that) and cannot be used to learn the usage of the current sfForm implementation. It is quite long, so you might prefer to download the Markdown version and read it offline. Being a first draft, this document is a call for comments, both about its structure and its content. And if you are interested in implementing the differences between what this document describes and what is currently implemented in the symfony framework, please contact me.

Read more »

Document-Driven Development in Practice: Rethinking sfForms

If you've watched or read my presentation on Documentation-Driven Development, you may wonder how to put that new methodology into action. A practical example is often better than a long explanation, so let's see ho to apply it to the new Forms sub-framework introduced by symfony 1.1.

Not DDD

In order to use the new sfForm library, you must either read a book (not yet completely written) or dive into the source code and guess how to use it. To my mind, this is pretty much the contrary of what leads to a large adoption.

The Form framework was designed with power in mind, and reaches this goal very well: you can use it to create forms of any level of complexity, including forms embedding other forms, forms with a variable number of fields, forms split into several steps ("wizards"), etc. It is very much object oriented, so everything can be reused or overridden.

But unfortunately, in order to create a simple form, you need to learn a lot more and write a lot more code than what you used to do in symfony 1.1. The current Forms documentation describes the API and justifies its implementation. It goes very much into the details of each part of the sub-framework, and quite early in the learning process. The result - for me, at least - is that the reader feels overwhelmed by the huge amount of classes, features and options, and dismisses the whole sub-framework for being too complex.

"Let's use that new Form stuff for complex forms and keep the current form helpers and YAML validation for everyday forms", I hear. That's a pity, because once you understand how the new Forms sub-framework works and accept its verbosity, there is no good reason to stick with the old system.

An Ideal sfForm Documentation

I think that a piece of documentation is missing. This piece is probably an introduction to the Form sub-framework.

In symfony 1.0, a single chapter of the book was enough to master forms for most use cases. Even if the new form sub-framework is more powerful than the 1.0 one, it should not be more complicated to learn and use in similar cases. So the sfForms introduction should be short, requiring at most one hour to read it.

After reading this documentation, an average developer should be able to use sfForms in 80% of the cases. That includes at least all the features described in the original Forms chapter of the symfony book:

  • Displaying a form
  • Available form helpers
  • Displaying a model-based form
  • Dealing with Foreign keys
  • Handling a form submission
  • Validating a form
  • Available validators
  • Repopulating a form
  • Complex use cases

The target audience would be people knowing some concepts about symfony, but not yet everything. In fact, they should know what the Chapters 1 to 9 of the symfony guide cover, not more. So some advanced concepts should probably be skipped, or explained only after the fundamental usage is clear.

This introduction should not require additional lookup in the Forms book. That means that it should be self-sufficient. It probably also means not including the justifications of the Forms implementation that you can find in the current Forms book. The reasons why the API was designed the way it is should become obvious at the end of the introduction. Expert customization and rare use cases should probably also be left aside.

The symfony 1.0 documentation introduces concepts and features in a certain order, with a precise purpose: not loading too much information into the reader's mind at a time. In a similar fashion, the forms introduction should be a linear piece of documentation, not a set of articles that you can read in any order with hyperlinks everywhere to break the reading flow.

The forms framework is powerful, but the current form book somehow translates that into length, and verbosity. On the contrary, I think the reader should feel exalted: the documentation should put him in a rush to start using the new forms. So the forms introduction should "tell a story", and gently lead the reader to a point where he feels he can grab the steering wheel and drive the car by himself.

API enhancements

The problem is that explaining the current API takes much longer than a single piece of documentation. That's because of the many options available, because of the many objects to learn, and because even the simplest things (like a list of form controls) look complicated (sfWidgetFormSchema).

There is not much choice to overcome this problem. In order to write a short and readable guide to the forms sub-framework, its API must be adapted. That's right, the API must be changed so that the documentation can be made shorter, and more usable. This is one of the principles of the Documentation-Driven Development methodology.

These API enhancements should be completely backward compatible, so that any existing application using the current sfForms implementation can continue to work seamlessly with the modified implementation. In a way, that qualifies the API enhancements as a simplicity layer on top if the existing code. As a side note, the current Forms book still remains indispensable for advanced usage.

Note that the API enhancements don't need to be implemented before the new documentation is published. The implementation comes second, after the documentation. That's another of the DDD principles: explain first, make it work afterwards. After all, project managers write requirements for web applications before they exist, all the time.

Do As I Do, Not As I Say

Some people are getting sick of reading me criticizing parts of the symfony framework. Well, I'm not criticizing: I'm actively improving.

Rethinking sfForms is a good example for a Documentation-Driven Development. To illustrate this methodology, I'm going to rewrite the Chapter 10 of the symfony book for symfony 1.1. That's right, the current Chapter 10, which describes the "old way" of doing forms, can be rewritten in a similar fashion and serve for symfony 1.1.

But since the current API requires too much explanation to be used, I'm going to introduce the necessary API changes to the sfForms library. I'll create and manage forms in a way slightly different from what the current API allows, to make it simpler to use - and to explain.

When the new Chapter 10 is published here in this very blog, this piece of documentation will be of no use since the features it describes won't be implemented yet. But I know that writing documentation is not enough to convince people (yet), so I will Implement the API changes as a second step to the exercise. As I'm not a very good developer, any help will be welcome during that phase (contact me If you want to give me a hand after the documentation is published).

If everything goes well, the implementation of the API changes will be be released as a symfony plugin - maybe called sfSimpleForms. I hope it can lead more developers to adopt the greatest open-source Forms framework around.

Developing for Developers: my SymfonyCamp08 Presentation

Did you attend this year's Symfony Camp? It was a great event, the unique occasion to meet the core team of the symfony framework. I had the opportunity to give a talk there, and you can now watch it online:

Developing for Developers
View SlideShare presentation or Upload your own. (tags: symfony php)

Don't hesitate to comment on this presentation on SlideShare.

Thanks to all the great people that I met there who gave me a feedback on my work, encouragements or advice. Thanks to Dutch Open Projects for the organization - and for inviting me. It was a great pleasure to exchange about symfony, its past, present, and future, with so many enthusiastic people.

Update: It seems that my slideshow has been featured on the SlideShare homepage by the SlideShare editorial team.