Bedenkingen over XML

Auteur: Mark Hooijkaas
Versie: $Revision: 1.1 $
Datum: $Date: 2004/05/31 14:16:29 $

In dit document wil ik twee mogelijke problemen beschrijven die ik zie bij het gebruik van XML als transport en specificatie formaat voor gestructureerde berichten in een message broker architectuur. Hoewel het XML formaat een krachtig, gestandaardiseerd en netjes formaat is, zie ik toch twee belangrijke problemen:
  1. In XML zijn element name en type hard aan elkaar gekoppeld.
  2. Er is behoefte aan uitgebreidere specificatie mogelijkheden dan XML waarschijnlijk kan bieden.
Het eerste probleem hierbij is zeer fundamenteel van aard, en kan als gevolg hebben dat men geen gebruik kan maken van XML en met name DTD specificaties op de manier die men zou willen. Het tweede probleem, betekent dat men naast of bovenop XML en DTD's nog een extra mechanisme nodig heeft voor exacte specificaties. Beide problemen zijn wel te overkomen, maar niet op een manier die in lijn is met de manier waarop XML bedoeld is. Dit document hoopt, door het signaleren hiervan, de verwachtingen rondom XML indien nodig bij te stellen. In de volgende twee secties zal ik beide problemen nader toelichten.

Probleem 1: element-naam en element-type aan elkaar gekoppeld

In alle mij bekende programmeertalen (waaronder Java, C, C++, Pascal en Visual Basic) zijn de naam van een variabele en zijn type onafhankelijk van elkaar. Ook in gestructureerde types in deze talen (een record in Pascal, een struct in C en C++, een class in C++ en Java), geldt dat de veldnamen onafhankelijk van hun types zijn. Ook buiten het gebied van programmeertalen, zoals bijvoorbeeld in SQL databases, ziet men deze zogenaamde "orthogonaliteit" terugkeren. Dit alles doet vermoeden dat dergelijke onafhankelijkheid zeer fundamenteel van aard is, en tot problemen kan leiden als de onafhankelijkheid ontbreekt.

Tot mijn spijt, is binnen normaal gebruik van XML de naam van een element (zijn tag) direct gekoppeld aan zijn type. Immers in een DTD wordt voor ieder element naam gedefinieerd welke sub elementen er in voor kunnen komen. Men kan niet een bepaald element type definieren (b.v. TELEFOONNUMMER) en dit onder verschillende namen gebruiken. Gevolg hiervan is dat de namen van elementen zowel de syntax (het type) als de semantiek (het gebruik) moeten representeren. Om bij het telefoonnummer voorbeeld te blijven: men wil van een bepaald data element aangeven dat het de telefoonnummer syntax heeft (d.w.z. het bestaat uit een netnummer element en een abonneenummer element), en tegelijkertijd dat het semantisch om een faxnummer gaat. Dit heeft leidt tot volgende complicaties:

  1. Het is niet mogelijk hetzelfde (element)type voor verschillende semantieken te gebruiken.
  2. Het is niet mogelijk dezelfde element naam voor verschillende types te gebruiken.

Complicatie 1.1: geen hergebruik typedefinities

Het bovenstaande telefoonnummer voorbeeld geeft al aan waar het probleem ligt. Nog duidelijker wordt dit probleem als men binnen één element verschillende velden heeft van hetzelfde type. Voorbeelden hiervan zijn het willen opslaan van een telefoonnummer, faxnummer en prive-nummer van een persoon, of het willen opslaan van een contractant vestiging, betalers vestiging en afnemer vestiging van een telecom pakket. Er zijn diverse mogelijkheden om dit probleem te omzeilen. Vaak kiest men om een extra tussenliggende veld te definieren, bijvoorbeeld:
  <PERSOON>
    <FAXNUMMER>
      <TELEFOONNUMMER>
        <NETNUMMER>050</NETNUMMER>
        <ABONUMMER>1234568</ABONUMMER>
      </TELEFOONNUMMER>
    </FAXNUMMER>
    <WERKNUMMER>
      <TELEFOONNUMMER>
        <NETNUMMER>070</NETNUMMER>
        <ABONUMMER>1234568</ABONUMMER>
      </TELEFOONNUMMER>
    </WERKNUMMER>
  </PERSOON>
Oftewel, als men aan de velden wil refereren, dan heeft men de volgende geneste velden:
  PERSOON.FAXNUMMER.TELEFOONNUMMER.NETNUMMER
  PERSOON.WERKNUMMER.TELEFOONNUMMER.ABONUMMER
  etc
Bij deze techniek worden dergelijke tags onnodig lang en diep genest en daardoor slecht leesbaar. Hoewel dit in theorie geen probleem hoeft te zijn, kan dit tot fouten leiden.

Veel belangrijker probleem echter is dat men met deze methode voor ieder nieuw semantisch gebruik, nieuwe element types moet definieren. Immers, voor bovenstaand voorbeeld is een FAXNUMMER en een WERKNUMMER element type gedefinieerd, die ieder slechts één subelement bevatten, te weten TELEFOONNUMMER. Deze nieuwe types zijn eigenlijk een beetje nep-types, die weer extra werk kosten om te onderhouden en de namespace van element-types kunnen vervuilen. Als voordeel van dergelijke nep-types wordt wel eens genoemd dat men hierdoor aan b.v. een faxnummer, later extra elementen kan toevoegen. Dit is echter een non-argument, want dan zou men net zo goed ook voor alle andere elementen nieuwe types kunnen/moeten aanmaken, en in feite nooit types hergebruiken.

Tot slot valt nog op te merken dat er ook andere manier zijn om hiermee om te gaan. Volgens mij hebben deze alternatieven echter ieder weer hun eigen problemen en zijn ze minder in lijn met de gedachte achter XML. Een altrenatief is bijvoorbeeld om een veldnaam als element-attribuut opnemen (of zelfs een typenaam). In dit voorbeeld heeft een persoon meerdere telefoonnummers, ieder met een verschillende qualifier. Bij deze oplossing is echter weer moeilijk af te dwingen dat b.v. werknummer verplicht is en faxnummer optioneel.

Complicatie 1.2: geen hergebruik elementnaam

Deze tweede complicatie is eigenlijk het omgekeerde van de eerste complicatie. In plaats van dat men hetzelfde element type type bij verschillende namen/toepassingen wil gebruiken, wil men nu dezelfde elementnaam voor verschillende types gebruiken. Dit komt vooral voor bij hele generieke namen zoals ITEM, GEBRUIKER, etc. Binnen de specificatie (DTD) van één specifiek bericht zal dit niet snel tot problemen leiden. Als men echter tot een bedrijfsbreed gegevens model wil komen (of op zijn minst daar naar streven) kan dit tot aanzienlijke afstemmings problemen leiden. Zeker wanneer, als gevolg van de vorige complicaties, de element types/namen worden vervuild met allerlei nep-types. Door gebruik te maken van goede naming-conventions kan dit probleem omzeild worden, maar hierdoor worden de namen weer onnodig lang en onleesbaar, omdat ze informatie bevatten die ook uit de context afgeleid had kunnen worden. Bij naming conventies zou men iets gebruiken zoals
  ORDER.ORDER_WERKNUMMER
  en
  PERSOON.PERSOON_WERKNUMMER
in plaats van
  ORDER.WERKNUMMER
  en
  PERSOON.WERKNUMMER

Probleem 2: behoefte aan uitgebreidere specificatie mogelijkheden

Het tweede probleem ligt mogelijk bij een stuk onbekendheid over XML mijnerzijds. Wat belangrijk is, is de noodzaak om in de bericht specificatie meer dan alleen de structuur van het bericht vast te leggen. Hierbij gaat het om extra eisen die men aan het bericht stelt, in de vorm van pre condities en post condities. Niet alleen dienen deze condities netjes gedocumenteerd (gespecificeerd) te worden, ze dienen ook runtime gecontroleerd te kunnen worden. Door deze controles kunnen clients problemen constateren voordat het bericht daadwerkelijk verstuurd wordt. Dit is o.a. van belang bij user interfaces, waarbij de gebruiker direct verteld kan worden dat hij niet voldoende of inconsistente informatie heeft ingevoerd. Maar ook bij het aannemen van berichten is het nuttig als hier al gestandaardiseerd zoveel mogelijk gecheckt wordt, voordat er acties naar diverse systemen worden uitgezet. Tot slot helpt het bij het integreren en testen van systemen, waarbij men "slechts" hoeft te garanderen dat een systeem binnen de gestelde pre-condities correct werkt, terwijl alle berichten die daar niet aan voldoen automatisch uitgefilterd worden (en dus ook geen schade aan kunnen richten).

Hieronder volgt een opsomming van type condities waar aantoonbaar behoefte aan is gebleken:

Deze lijst is wellicht verre van volledig, maar geeft een aardige opsomming van precondities die we graag netjes gespecificeerd en gecontroleerd zouden zien. Van alle genoemde voorbeelden zijn we tegen problemen aangelopen die makkelijker te herkennen of zelfs te voorkomen waren geweest, als we dergelijke condities duidelijk gespecificeerd waren en automatisch gecheckt worden.

Een nog veel belangrijkere reden om mogelijkheden te bieden om dergelijke condities te specificeren is om ze zichtbaar te maken. Als men dergelijke condities niet in de specificaties kwijt kan, of niet daaruit kan laten controleren, is men gedwongen ergens binnen de implementatie de checks alsnog uit te voeren. Hierdoor worden de diverse checks verborgen in de code, en zijn niet zichtbaar voor partijen die gebruik willen maken van een specifiek bericht. Het is mijn stelling dat al deze eisen in de specificatie thuis horen, en niet in de code (als men dit ook in de code moet checken, loopt men het risico dat de code en de specificatie uit de pas gana lopen). Wat ik tot nu toe van XML gezien heb kan men daar in een DTD slechts een aantal van deze condities in kwijt (met name syntactische).

Ook postcondities kunnen eventueel gebruikt worden. Men zou bijvoorbeeld in de specificaie van iedere request bericht ook kunnen beschrijven welke mogelijke reply berichten daar op te verwachten zijn. Hierbij kan één request resulteren in verschillende types reply berichten (meestal één type bij een succesvolle verwerking, en verschillende "exception" berichten als er iets fout gegaan is). Het is ook denkbaar dat op één request bericht meerder reply berichten terugkomen (al of niet van verschillende types). Hierbij valt te denken aan meerdere status terugkoppelingen voor iedere fase die een order doorloopt, of het in hapklare brokken hakken van een grote resultset.

Tot slot

overige wensen

Naast bovengenoemde problemen hebben we ook nog andere features ontdekt waarvan ik betwijfel of XML dat ondersteunt:

Conclusies

XML lijkt een veelbelovende ontwikkeling, met vele voordelen: Toch zijn er ook een paar zeer serieuze problemen te overwinnen.