Zu dem für dieses Framework verwendeten SML-Dateiformat gibt es eine Anzahl populärer Alternativen. Der folgende Abschnitt wird einige dieser Alternativen vorstellen, vergleichen und die Ergebnisse diskutieren.
Im Folgenden sollen verschiedene Teilaspekte betrachtet werden:
Da nicht ausgeschlossen werden kann, dass eine Bearbeitung des Quelltextes der Dateien teilweise von Hand erfolgen muss, ist der Lesbarkeit des Quelltextes ein Kriterium, das beleuchtet werden soll. Die Syntax sollte im Idealfall intuitiv zu erfassen sein. Insbesondere ist dies wichtig, da zum gegenwärtigen Zeitpunkt nur für eine Untermenge der Gesamtheit der Konfigurationsmerkmale des Frameworks eine grafische Oberfläche bereitgestellt werden kann. In Anbetracht der Fülle an Optionen ist es darüber hinaus auch auf absehbare Zeit eher unwahrscheinlich, dass eine vollständige Abdeckung erreicht werden kann. Es stellt sich ohnehin die Frage, ob dies überhaupt wünschenswert wäre. Schließlich sollte auch berücksichtigen werden, dass es prinzipiell erfahrene Anwender gibt, welche bewusst und absichtlich auf die Funktionen einer "schwerfälligen" GUI verzichten, weil sie diese eher als Behinderung anstatt als Bereicherung empfinden.
Ein interessanter Faktor ist auch die Performance, da das Dateiformat einem eventuell zeitkritischen Zweck genügen soll, nämlich der Initialisierung des Frameworks. Begründet dadurch, dass die Dateien bei jedem Aufruf des Frameworks neu gelesen und dabei eventuell auch durch einen Parser untersucht werden müssen bevor ihre Informationen verfügbar sind, sollte dieser Vorgang mit möglichst geringen Kosten im Hinblick auf die Rechenzeit auskommen. Nicht immer ist ein sinnvoller Vergleich möglich, wo sich ein Vergleich jedoch anbietet sollte er durchgeführt werden.
Darüber hinaus sollten die Grenzen des jeweiligen Dateiformats beachtet werden. Wenn es Faktoren gibt, welche dazu führen können, dass ein Einsatz unter bestimmten Bedingungen nicht mehr sinnvoll ist, sollten diese genannt werden.
Die Portabilität der Dateien in andere Programmiersprachen ist eine der Stärken von XML. Parser für XML sind in den Funktionsumfang nahezu jeder modernen Skript- oder Programmiersprache integriert. Dies fällt jedoch für dieses Anwendungsgebiet – die Initialisierung des Frameworks – nicht ins Gewicht, da die für die Umsetzung des Frameworks gewählte Sprache ist PHP und Implementierungen des Frameworks in anderen Sprachen existieren zurzeit nicht.
Das aktuelle Werkzeug der Wahl zur Behandlung von XML, welches gleichermaßen für PHP 4 als auch PHP 5 verfügbar ist, ist zum gegenwärtigen Zeitpunkt der interne XML-Parser. Dieser XML-Parser besitzt allerdings eine Schwachstelle. Er ist lediglich zum Lesen von XML-Dateien verwendbar, nicht jedoch zum Schreiben. Eine Implementierung zum Erzeugen von XML-Dateien ist erst für PHP ab Version 5 als Standardkomponente enthalten.
Hinzu kommt, dass mithilfe des XML-Parsers ein assoziatives Datenfeld aus einer XML-Datei zu erstellen ähnlich viel Programmieraufwand benötigt, wie für das Schreiben eines Skripts für das Laden einer SML-Datei erforderlich gewesen ist. Allerdings ist dies mit dem Risiko verbunden, dass sich die Implementierung des XML-Parsers in einer späteren Veröffentlichung der Sprache möglicherweise verändert, auch wenn dies grundsätzlich unwahrscheinlich ist. Zudem gibt es keine sonstigen wesentlichen Vorteile dieser Implementierung, abgesehen von der allgemeinen Beliebtheit von XML als Dialekt.
Als weiteres Argument wäre die Performance zu beleuchten. Dies gestaltet sich jedoch alles andere als unproblematisch und die Ergebnisse sind nur unter Vorbehalt zu betrachten, da diese abhängig sind vom eingesetzten Werkzeug. Derer gibt es viele für das XML-Format, selbst wenn sich auf PHP als solches beschränkt wird.
Um einen Vergleich anstellen zu können, soll ein einfaches XML-Dokument geladen und in ein Datenfeld übertragen werden.
Zum Vergleich hier der Quelltext des verwendeten XML-Dokuments.
<?xml version="1.0"?>
<root>
<array name="channel">
<scalar name="title">Test</scalar>
<scalar name="link">about:blank</scalar>
<scalar name="description" />
<scalar name="language">de-de</scalar>
<array name="0">
<scalar name="title">Testeintrag 1</scalar>
<scalar name="pubDate">Do, 9 Jun 2005 13:23:18 +0200</scalar>
<scalar name="description"><![CDATA[Testeintrag]]></scalar>
<scalar name="link" />
<scalar name="author">Testautor</scalar>
</array>
<array name="1">
<scalar name="title">Testeintrag 2</scalar>
<scalar name="pubDate">Do, 9 Jun 2005 13:23:53 +0200</scalar>
<scalar name="description"><![CDATA[Testeintrag]]></scalar>
<scalar name="link" />
<scalar name="author">Testautor</scalar>
</array>
<array name="2">
<scalar name="title">Testeintrag 3</scalar>
<scalar name="pubDate">Do, 9 Jun 2005 13:24:18 +0200</scalar>
<scalar name="description"><![CDATA[Testeintrag]]></scalar>
<scalar name="link" />
<scalar name="author">Testautor</scalar>
</array>
<array name="3">
<scalar name="title">Linktest</scalar>
<scalar name="pubDate">Do, 9 Jun 2005 13:24:36 +0200</scalar>
<scalar name="description"><![CDATA[Testeintrag]]></scalar>
<scalar name="link">about:blank</scalar>
<scalar name="author">Testautor</scalar>
</array>
</array>
</root>
Anschließend das Gleiche im SML-Format.
<channel>
<title>Test</title>
<link>about:blank</link>
<language>de-de</language>
<0>
<title>Testeintrag 1</title>
<pubDate>Do, 9 Jun 2005 13:23:18 +0200</pubDate>
<description>Testeintrag</description>
<author>Testautor</author>
</0>
<1>
<title>Testeintrag 2</title>
<pubDate>Do, 9 Jun 2005 13:23:53 +0200</pubDate>
<description>Testeintrag</description>
<author>Testautor</author>
</1>
<2>
<title>Testeintrag 3</title>
<pubDate>Do, 9 Jun 2005 13:24:18 +0200</pubDate>
<description>Testeintrag</description>
<author>Testautor</author>
</2>
<3>
<title>Linktest</title>
<pubDate>Do, 9 Jun 2005 13:24:36 +0200</pubDate>
<description>Testeintrag</description>
<link>about:blank</link>
<author>Testautor</author>
</3>
</channel>
Zum Vergleich wird PHP 4 mit dem im Standard enthaltenen XML-Parser herangezogen. Dabei wird so vorgegangen, dass vor und nach jedem Parsen jeweils mithilfe des Befehls "microtime" eine Messung durchgeführt wird. Die Differenz zwischen beiden Werten wird in Millisekunden ausgegeben. Es kommt dabei nicht darauf an, wie viele Millisekunden die eine oder andere Technik schneller ist. Das objektiv zu beurteilen ist mit diesem Testverfahren selbstverständlich unmöglich, denn das Verfahren ist viel zu rudimentär um repräsentative Ergebnisse zu liefern.
Die Konfiguration des Testsystems kann in diesem Fall vernachlässigt werden, da lediglich die Größenordnung der Differenz zwischen beiden Techniken betrachtet werden soll.
Äußert problematisch für eine objektive Bewertung ist zudem der unglückliche Umstand, dass der XML-Parser zur Behandlung der Start-Tags, End-Tags und CDATA-Bereiche Einschübe aus handgeschriebenem PHP-Code benötigt. Es wäre somit denkbar, dass Effekte durch mehr oder minder performanten PHP-Code das Ergebnis der Messung verfälschen. Daher wird der XML-Parser sowohl einmal mit einer vergleichbaren Implementierung, als auch ein zweites Mal zum Vergleich ohne irgendeine Implementierung gemessen.
Ziel des Tests ist es nicht, ein Votum zu treffen für oder gegen den Einsatz des XML-Parsers. Vielmehr soll sich zeigen, ob es deutliche Unterschiede zwischen beiden Varianten gibt. Insbesondere, ob die SML-Variante um Größenordnungen langsamer als der XML-Parser ist. Dies könnte einen Hinweis darauf liefern, dass die gefundene Lösung möglicherweise aus Gründen schlechter Performance nicht für das Framework geeignet sein könnte.
Für diese recht bescheidene Aufgabenstellung sollte diese äußert einfache Testmethode trotz allem ausreichend genaue Ergebnisse liefern.
XML-Parser 1 | XML-Parser 2 | SML-Skript | Differenz SML zu XML 1 |
Differenz SML zu XML 2 |
---|---|---|---|---|
0,003685s | 0,001813s | 0,001626s | -0,001153s (31%) | -0,000187s (10%) |
0,003410s | 0,001666s | 0,001255s | -0,002155s (63%) | -0,000411s (24%) |
0,003367s | 0,001629s | 0,001312s | -0,002055s (61%) | -0,000317s (19%) |
0,003394s | 0,001614s | 0,001240s | -0,002154s (63%) | -0,000374s (23%) |
0,003381s | 0,001618s | 0,001228s | -0,002153s (63%) | -0,000390s (24%) |
0,003386s | 0,001613s | 0,001400s | -0,001986s (59%) | -0,000213s (13%) |
0,003387s | 0,001620s | 0,001296s | -0,002091s (61%) | -0,000324s (20%) |
0,003658s | 0,001617s | 0,001247s | -0,002411s (65%) | -0,000370s (22%) |
0,003678s | 0,001633s | 0,001454s | -0,002224s (60%) | -0,000179s (10%) |
0,003725s | 0,001613s | 0,001573s | -0,002152s (58%) | -0,000040s (2%) |
Vergleich der Performance zwischen XML-Parser und SML-Skript (Auszug)
1 XML-Parser bei Verwendung einer zum SML-Skript vergleichbaren Implementierung
2 XML-Parser im Leerlauf, ohne Verarbeitung der Eingabe
Betrachtet man den obigen, kurzen Auszug der Ergebnisse so fällt einerseits auf, dass der mit PHP-Code bestückte XML-Parser weniger performant agiert hat als das SML-Skript. Dies könnte jedoch wie bereits erwähnt auch eine Frage weniger performanter Programmierung sein. Betrachtet man jedoch Spalte 2 ("XML-Parser 2") im Vergleich zu Spalte 3 ("SML-Skript") so sieht man, dass auch in diesem Fall die SML-Variante nah bei den Werten des XML-Parsers liegt. Dies ist insbesondere bemerkenswert, da der XML-Parser in diesem Fall gar kein Ergebnis produzierte, da keine Implementierung zur Bearbeitung des Inhalts angegeben wurde. Aus diesem Grunde kann das Argument, dass eine ungünstig gewählte Implementierung den XML-Parser verlangsamt haben könnte, nicht mehr aufrecht erhalten werden.
Dieser Test lieferte folglich keinen Hinweis darauf, dass die Leistungsfähigkeit der Implementierung einen negativen Effekt auf die Performance der gesamten Anwendung ausüben könnte.
Syntaktisch gesehen unterscheidet sich die Benutzung von SimpleXML für den Entwickler nur unwesentlich von der Verwendung des SML-Skripts, wie der nachfolgende Quellcodeauszug verdeutlicht.
<?php
$sml = SML::getFile("test.config");
$xml = simplexml_load_file("test.xml");
?>
Der einzige offensichtliche Unterschied liegt im Typ des Rückgabewerts.
Während die SML-Variante ein assoziatives Datenfeld als Ergebnis
liefert, gibt SimpleXML ein Objekt vom Typ "SimpleXMLElement" zurück.
Man mag geteilter Auffassung darüber sein, welche Variante die
glücklichere Wahl ist.
Gegen SimpleXML spricht, dass es die Namen von Tags und Attributen auf Namen von Objekten und der Eigenschaften in PHP ab. Das ist problematisch, weil diese in PHP und XML jeweils unterschiedliche Zeichen enthalten dürfen. Zum Beispiel betrifft dies das Zeichen '-', welches in PHP nicht für die Benennung von Variablen verwendet werden darf. Folglich kann man zum Zeitpunkt der Erstellung dieses Dokuments über SimpleXML auf einen Tag namens <foo-bar> nur sehr umständlich zugreifen.
Initialisierungsdateien, häufig abgekürzt mit der Dateiendung "ini", sind ihrerseits eine geeignete Alternative, sofern keine Abbildung von komplexen Strukturen erforderlich ist. Die Darstellung von Schlüsseln, insbesondere bei tief verschachtelten Informationen, kann jedoch im Einzelfall unübersichtlich werden. Das Format bietet syntaktisch einen einfachen Aufbau. Allerdings müssen dem Format einige Abstriche gegenüber XML zugestanden werden. Es fehlt zum Beispiel die typische Schreibweise in Form von Tags, welche derzeit populär ist. Das Erstellen einer DTD oder einer vergleichbaren Datei, welche die Struktur des Dateiformats beschreibt, ist sowohl praktisch als auch aus theoretischen Überlegungen heraus nicht möglich. Dies ist jedoch kein Nachteil. Bedenkt man, dass die vordergründige Aufgabe dieses Dateiformats darin besteht, eine Abbildung von beliebig strukturierten assoziativen Datenfeldern aus einer Skript- oder Programmiersprache heraus auf ein Dateiformat zu realisieren, wird deutlich, dass die Vorgabe einer statischen Struktur nicht sinnvoll ist. Ideal wäre eine Kombination, welche die Vorteile beider Formate in sich vereint.
Der folgende Quellcodeauszug zeigt ein Beispiel für eine Initialisierungsdatei.
[STORE\0]
type=book
author=Dr. A Beispiel
[STORE\0\TITLE]
main=Protomaterie
subtitle=Alpha et Omega
[STORE\1]
type=cd
author=Barbara Sänger
[STORE\1\TITLE]
main=Best-Of
Eine weitere Alternative ist die Verwendung von JSON. Im Folgenden ein Beispiel:
"STORE" : {
"0" : {
"type" : "book",
"author" : "Dr. A Beispiel",
"TITLE" : {
"main" : "Protomaterie",
"subtitle" : "Alpha et Omega"
}
},
"1" : {
"type" : "cd",
"author" : "Barbara Sänger",
"TITLE" : {
"main" : "Best-Of"
}
}
}
PHP bietet die Möglichkeit, ähnlich wie beispielsweise Java, mit den Befehlen "serialize" und "unserialize" Variablen zu serialisieren und wiederherzustellen.
Der folgende Quellcodeauszug zeigt ein Beispiel.
a:1:{s:7:"CHANNEL";a:7:{s:5:"TITLE";s:4:"Test";s:4:"LINK";s:11:"about :blank";s:8:"LANGUAGE";s:5:"de-de";i:0;a:4:{s:5:"TITLE";s:13:"Testein trag 1";s:7:"PUBDATE";s:29:"Do, 9 Jun 2005 13:23:18 +0200";s:11:"DESC RIPTION";s:11:"Testeintrag";s:6:"AUTHOR";s:9:"Testautor";}i:1;a:4:{s: 5:"TITLE";s:13:"Testeintrag 2";s:7:"PUBDATE";s:29:"Do, 9 Jun 2005 13: 23:53 +0200";s:11:"DESCRIPTION";s:11:"Testeintrag";s:6:"AUTHOR";s:9:" Testautor";}i:2;a:4:{s:5:"TITLE";s:13:"Testeintrag 3";s:7:"PUBDATE";s :29:"Do, 9 Jun 2005 13:24:18 +0200";s:11:"DESCRIPTION";s:11:"Testeint rag";s:6:"AUTHOR";s:9:"Testautor";}i:3;a:5:{s:5:"TITLE";s:8:"Linktest ";s:7:"PUBDATE";s:29:"Do, 9 Jun 2005 13:24:36 +0200";s:11:"DESCRIPTIO N";s:11:"Testeintrag";s:4:"LINK";s:11:"about:blank";s:6:"AUTHOR";s:9: "Testautor";}}}
Diese Lösung ist ohne Zweifel sehr performant. Der Befehl "unserialize" arbeitet mit dieser Eingabe noch einmal um den Faktor 2 schneller als SimpleXML. Problematisch ist jedoch die Lesbarkeit des erzeugten Datenstroms. Für händische Eingriffe ist diese Darstellung offensichtlich denkbar ungeeignet. Da eine gute Lesbarkeit für das Framework jedoch unabdingbar ist, wurde von einer Realisierung in dieser Form bis auf Weiteres abgesehen.
Thomas Meyer, www.yanaframework.net