À propos des librairies de génération de formulaires HTML
Il y a un certain temps (ntd - février 2005), j'ai écrit un billet à
propos de la génération de formulaires web. J'y faisais part de mon expérience
acquise lors du développement de FunFormKit, du développement des premières
versions de FormEncode, et j'y expliquais aussi ce qu'est devenu
FormEncode (uniquement une librairie de validation).
Depuis, sont arrivées quelques nouvelles librairies de génération de formulaires
web dans l'écosystème Python;
ToscaWidgets,
Django newforms, et quelques autres dont j'ai entendu parler.
Je n'aime pas critiquer gratuitement le travail des autres, mais je
tiens à dire que je pense que ces librairies ont adopté une mauvaise stratégie pour
atteindre leurs objectifs.
Écrire une librairire de génération de formulaires est une tâche difficile.
Il faut trouver le bon compromis entre une certaine simplicité d'utilisation et
l'étendue des fonctionnalités.
Potentiellement, le nombre de fonctionnalités pour ce type d'outil est très
élevé. Exemples :
- comment modifier finement le code HTML généré ?
- comment contrôler la mise en forme (le layout) ?
- comment gérer la répétition d'éléments ?
- comment gérer les éléments qui requièrent du Javascript ?
- comment gérer les ressources coté serveur du type CSS ou Javascript ?
- Comment gérer les communications client-serveur, par exemple supporter
l'auto-complétion ?
Une librairie qui gère autant de fonctionnalités ne peut pas rester simple à
utiliser. Une "petite" librairie qui reste simple ne pourra gérerer qu'une
petite partie de ces fonctionnalités.
Cependant, pour générer des formulaires "simplistes", il n'est pas utile
d'avoir recours à une librairie de génération de formulaires.
Cycle de vie de la création d'une librairie de génération de formulaires
Je vais maintenant expliquer pourquoi, à cause de leur conception, ils
ne peuvent pas obtenir un bon compromis entre simplicité et fonctionnalité.
Il existe des problèmes qui n'ont pas de solution. Et contrairement aux
apparences, c'est le cas des outils de générations de formulaires.
Le cycle de vie de création et de maintenance d'une librairie de génération
de formulaires est pratiquement toujours le même.
Un développeur a certain besoins. Généralement il n'aime pas écrire du code
HTML bien que cela ne le dérange pas de travailler avec un langage de template
qui est plus difficile à utiliser. Il n'est sans doute pas très excité par
les tâches manuelles et fabriquer une librairie de génération de formulaires
est une agréable diversion.
Dans tous les cas, il fait le bon choix (enfin, celui qu'il pense
être le bon) et il essaie d'utiliser une librairie existante.
Il se trouve que la librairie est complexe à utiliser, elle ne
correspond pas à la façon dont il a appréhendé le problème, il est difficile
d'identifier l'origine des erreurs, les petits ajustements qu'il souhaite
apporter (lui, son chef ou son client) sont à l'origine de la plupart de ses
difficultés.
Et là, il se dit « Je peux faire cela plus simplement ! ».
Le développeur a raison. Il sait exactement ce dont il a besoin (maintenant),
et ce qui peut améliorer sa productivité.
Il crée donc une nouvelle librairie de génération de formulaires web.
Le problème est que la vie de cette nouvelle librairie ne s'arrête pas là.
Elle ne peut pas s'arrêter là !
Pourquoi ? Parce que quelqu'un utilise cette librairie, et par conséquent le
code doit être maintenu.
Une librairie de génération de formulaires est une chose difficile à
maintenir, car elle a toujours besoin d'évoluer.
Des nouveaux types de champ doivent être ajoutés. Des nouveaux cas particuliers
doivent être pris en compte. Pour ce qui concerne l'interface utilisateur, des
cas particuliers, non prévus initialement, doivent pouvoir être traités.
Une bonne interface utilisateur est généralement spécifique au besoin,
adapté au cas par cas. L'interface utilisateur doit être construite en
fonction du besoin de l'utilisateur final et non pas en fonction des
contraintes du développeur.
Avec le temps, le développeur a de nouveaux besoins.
Par exemple, une simple liste de cases à cocher contient un très grand
nombres de choix. Il faut maintenant pouvoir l'afficher sur deux colonnes.
Conséquence : pour gérer ce nouveau cas, le développeur ajoute un peu de code
à la fois dans la librairie et dans l'application.
Ensuite, le développeur souhaite que les champs textes contiennent le nom des
champs (leurs labels) quand leurs contenus sont vides. Suite à cela, le système
de validation devient un peu plus complexe à gérer.
Ensuite, le développeur aura peut être besoin de gérer des formulaires à
plusieurs étapes… Ou alors des formulaires avec des champs optionnels…
De fil en aiguille, à chaque fois du code est ajouté à la librairie
ainsi que dans l'application (à condition bien sûr, dans le meilleur des cas
d'avoir le contrôle de ces deux parties).
Avec le temps, la librairie devient de plus en plus complexe, tandis que
pendant ce temps, le développeur se familiarise avec son propre code
et devient de plus en plus distant des autres développeurs qui devront peut
être un jour intervenir dans son projet.
Et là, nous n'avons même pas abordé le sujet des non programmeurs qui
souhaitent seulement modifier un tout petit peu le rendu HTML du formulaire.
Ensuite vient le problème de turnover…
Et un jour, c'est la catastrophe, quelqu'un vient et dit « Je peux faire cela
plus simplement ! » et c'est reparti pour un tour, on recommence l'histoire
depuis le début.
Une autre approche
La partie validation
Je pense que le problème n'est pas pris par le bon coté. Je pense qu'il y a
une meilleur approche, mais je suis trop fainéant pour la réaliser.
Bon…, je vais expliquer le principe, avec le petit espoir que
quelqu'un réalisera le code :) .
Tout d'abord, la partie « validation » : j'aime la façon dont
FormEncode
fonctionne, je pense que la stratégie est bonne.
L'étape de validation est totalement indépendante du reste du système, vous
pouvez programmer le type de validation que vous souhaitez, vous pouvez
l'intégrer dans un autre système…
La partie « formulaire »
Ensuite, la partie « formulaire ».
La solution la plus simple est d'écrire directement le formulaire en
code HTML avec son langage de template préféré.
Mais ceci est ennuyeux, les développeurs vont se plaindre… Pourquoi ?
- Remplir les valeurs par défauts dans les champs est ennuyeux.
Il faut prendre en compte différents cas : les valeurs de la requête (par
exemple en mode modification), les valeurs par défauts lorsque le formulaire
est vide…
- La mise en place de l'affichage des messages d'erreurs est aussi une tâche
ennuyeuse.
- Il faut écrire correctement les balises <label>… ce qui est une tâche
rébarbative… c'est peut être ce qui explique que de très nombreux sites,
même de grande notoriété, n'intègrent pas ces balises.
- Je suppose que l'HTML est généralement casse-pieds, bien que le langage
soit seulement légérement plus verbeux que le code de programmation qui
permet de le remplacer.
- La partie Javascript peut être ennuyeuse, beaucoup de développeurs web ne sont
pas très à l'aise avec ce langage.
- Il est ennuyeux de placer correctement les fichiers ressources Javascript et
CSS, et d'effectuer ensuite la liaison des classes CSS avec les bonnes balises…
- Les appels Ajax sont réellement ennuyeux à mettre en place.
- Les imbrications de champs, les répétitions de groupes de champs… sont une
autre source d'ennuis.
- Et pour finir, il est difficile de réutiliser tout cela.
Ma réponse est que tous ces problèmes peuvent être résolus sans librairie de
génération de formulaires.
formencode.htmlfill répond aux points 1 et 2. Ce n'est pas
parfait, mais c'est utilisable.
Quelque chose comme
WebHelpers peut être utile pour le point 4.
Aucun de ce ces outils ne doit être la solution ultime. Ils peuvent tous
être améliorés mais attention, il ne faut pas pousser trop loin leurs
perfectionnement ! Sinon ils vont devenir de trop grands consommateurs
de temps.
Je pense que la mise en oeuvre d'un outil spécifique pour le point 6, pourrait
être pratique : j'imagine quelque chose comme
<input type="date" js-require="DateInput"> qui chargerait automatiquement
les bons fichiers Javascript et CSS, et qui appellerait du code là où est le
champ DateInput.
Les nouvelles spécifications Web Forms 2.0 de WHAT-WG peuvent
parfaitement gérer les points 7 et 8… un outil construit sur ce modèle
ferait parfaitement l'affaire.
Une fois que vous avez tout cela, je pense que le point 9 peut être plus ou
moins atteint.
En conclusion, vous n'avez pas besoin d'un framework de génération de
formulaires, vous avez juste besoin d'un outil tout simple qui génère du
code HTML et qui respecte certaine conventions.
Ce qui est remarquable , c'est que cette technique est uniquement basée sur
des abstractions déjà présentes : HTML et Javascript.
De plus, chaque outil peut être utilisé de manière indépendante. Il est
possible de remplacer chaque brique par autre chose, une nouvelle
implémentation… qui correspond parfaitement au besoin du projet.
Ce qui est difficile à accepter, c'est que ces outils semblent terriblement
simplistes, ils ont peu de fonctionnalités comparé aux systèmes de génération
de formulaires automatique.
Doucement mais surement, ces petits outils peuvent gagner la course, quelque
soit la manière… pendant ce temps, les autres systèmes de génération de
formulaires vont souffrir du mal du cycle de la réimplémentation…
Tandis que de simples outils vont mieux supporter les épreuves du temps.
Et même si ces simples outils n'arrivent pas à atteindre l'objectif souhaité,
il est possible d'en remplacer un ou plusieurs sans mettre en péril tout
l'édifice.
Maintenant, ça serait génial que quelqu'un se lance dans la fabrication
des pièces manquantes, car j'essaie vraiment de ne pas commencer de nouveaux
projets supplémentaires.
Ian Bicking