24 mars 2007

Le bon et le mauvais XML

Avant-propos : dans la famille des XML-istes, je suis plutôt du type early adopter (voir le paragraphe History sur REST-art). Mais l'usage d'XML doit se faire au profit des utilisateurs, et cela nécessite quelques précautions.

Limitez les hiérarchies
Finalement la structure arborescente d'XML est un inconvénient quand les hiérarchies deviennent trop profondes.


<message>
   <contract>
      <customer>
         <enterprise>
            <contact>
               <personn>
                  <addresses>
                     <postal>
                        <zipcode>75008</zipcode>
                     </postal>
                  </addresses>
                  [etc.]


Les mécanismes de parsing seront plus lents et compliqués à déboguer, surtout en SAX. Les chemins (XPath) seront plus lents à évaluer. Et finalement le message XML ne sera pas vraiment lisible, non évolutif et souvent erroné (problème des références circulaires non exprimables sous forme d'arbre), contrairement à la promesse d'origine. Paradoxalement, avec des hierarchies profondes, ce sont les XPath qui sont simples à lire, ce qui ne sert à rien : "message.contract.customer.enterprise.contact.personn.addresses.postal.zipcode"

Limitez-vous donc à 2 ou 3 niveaux maximum, et privilégiez l'usage d'éléments de liaison et de référence (xlink ou plus simplement ref/idref).

Limitez le dictionnaire
La taille des noms d'éléments (tags et attributs) est aussi problématique : elle ralentira le traitement des messages (écriture, lecture, parsing), elle occupera plus de bande passante lors des transferts, et elle utilisera plus de disque pourle stockage.
Mesurez la place inutilement consommée pour décrire quelques informations :


<postalAddress>
   <streetNumber>12</streetNumber>
   <streetName>avenue des Champs Elysées</streetName>
   <addressComplement>esc C</addressComplement>
   <zipcode>75008</zipcode>
   <city>Paris</city>
   <Country>France</country>
</postalAddress>


Nombre de caractères contenant l'information : 48 octets.
Taille totale du message : 257 octets.

Là encore c'est paradoxal : un avantage de XML, sa lisibilité par l'oeil humain, devient un inconvénient dès lors que l'on souhaite utiliser XML pour faire dialoguer des machines. Et pourtant aujourd'hui, plus aucun oeil humain ne lit ou écrit du XML, la plupart des développeurs utilisant des générateurs (XmlBeans, Jaxb, JEE5, .Net, etc.).

Certains pourraient rétorquer qu'au lieu d'écrire "streetNumber" on aurait pu écrire "sNu" et, pour "streetName", "sNa", etc. Dans ce cas je ne vois vraiment pas ce qu'on gagne à utiliser XML.

Ce qu'il aurait fallu faire (attention ici on n'est plus dans du XLM valide) : puisque le XML bien formé impose des balises équilibrées, leur fermeture peut être anonyme. Imaginez le même message écrit de façon plus économe :

<postalAddress>
   <streetNumber>12</>
   <streetName>avenue des Champs Elysées/>
   <addressComplement>esc C</>
   <zipcode>75008</>
   <city>Paris</>
   <Country>France</>
</>


De plus, si le message qui suivra est décrit au même format, pourquoi rappeler ce format que le système consommateur a déjà rencontré ?

<postalAddress>
   <>12</>
   <>avenue des Champs Elysées</>
   <>esc C</>
   <>75008</>
   <>Paris</>
   <>France</>
</>


Je trouve cette proposition pas moins lisible (surtout si on a reçu au moins une fois le dictionnaire), et facile à convertir en "full-XML".

Ceux qui disent que le XML avait l'avantage d'être vérifié par le récepteur avant parsing seront encore plus heureux d'utiliser MD5 pour conserver des possibilités de vérification sans alourdir le message lui-même.

Pour ceux que l'évolutivité (la naturelle compatibilité ascendante d'XML) intéresse, aucun problème : ma solution ne supprime pas la notion de tag XML, elle permet de n'en transporter que les éléments essentiels, pas à chaque message. Il faudra néanmoins transporter un numéro de version de message, mais c'est une pratique que je recommande déjà en XML.

Pour utiliser une autre optimisation d'XML voyez par exemple BiTXml.

Restreignez-vous au strict minimum en XML
Si vous consultez la description du protocole HTTP (RFC2616) et de MIME (RFC2045), vous verrez que pour la plupart des échanges les formats sont standardisés. Vous constaterez aussi que le transfert de données simples est couvert par le type de contenu "application/x-www-form-urlencoded" (ex: streetNumber=12&streetName=avenue%20des%20Champs%20Elysees&zipCode=75008), et ces syntaxes sont des standards utilisés par tous les outils Web ainsi que les librairies associées dans tous les environnements (Java, .Net, PHP, Perl, C++, etc.).

Il ne reste au fond que des rares cas de données très structurées qui nécessitent l'usage de XML lors d'échanges M2M (machine to machine). Malgré cette évidence, les frameworks de développement de Web Services vous imposent l'usage de SOAP avec du XML auto-généré de manière opaque. .Net était déjà à l'extrême dans ce sens, JEE5 pousse le bouchon encore plus loin avec un comportement qui sera aléatoire selon le serveur d'application choisi (usage des annotations @Xxx).

Conclusion
Pour synthétiser, utilisez XML dans des messages à hiérarchie limitée (2 ou 3 niveaux), aux tags explicites mais pas trop longs, aux liens entre éléments réifiés, et uniquement si vous n'avez pas d'autre choix.
En définitive XML ressemble à une bonne idée non finalisée à utiliser exceptionnellement plutôt qu'à une solution universelle.

Pour plus d'arguments voir aussi le Guide d'usage de REST-art.