vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


Woche 1

Tag 7

Fehlerbeseitigung und Optimierung in JavaScript

Am Ende der ersten Woche sollten Sie schon einiges über Programmierung im Allgemeinen und JavaScript im Speziellen sowie die allgemeine Webseitenerstellung mit HTML wissen. Insbesondere können Sie mittlerweile so viel Stoff, dass es leicht möglich ist, eigenständig zu experimentieren. Dabei werden Sie aber unweigerlich auf einige Probleme stoßen. Deshalb wollen wir uns mit Fragestellungen befassen, die solche Probleme umschreiben und Ihnen Lösungsansätze anbieten. Wir befassen uns mit den folgenden Themen:

Fehler

Dieser Abschnitt soll mit einer harten Behauptung begonnen werden:

Es gibt kein etwas komplexeres Programm/Script ohne Fehler!

Zumindest nicht, bevor es nicht gründlichst durchgetestet und bereinigt wurde (und auch dann sind absolut fehlerfreie - etwas aufwendigere - Programme die absolute Ausnahmen, wie die unseligen Windows- Anwendungen mit ihren Schreibschutzverletzungen beweisen). Wenn Sie also Ihre Scripte oder Webseiten erstellen, werden diese während der Erstellungsphase immer wieder fehlerhaft sein. Programmieren bedeutet, Fehler zu machen. Diese müssen dann aber gefunden und beseitigt werden, bis das Script oder die Webseite fehlerfrei ist (soweit man es überblicken kann). Dann erst ist ein Script oder eine HTML-Seite fertig und kann veröffentlicht werden.

Bei HTML sind Fehler beileibe nicht so schlimm wie bei Programmiersprachen. Es gibt ja das Prinzip der Fehlertoleranz in HTML, das besagt, dass falsche Anweisungen einfach ignoriert werden. Wenn Sie unter HTML einen Fehler machen, kann nicht viel passieren. Meist schreiben Sie eine falsche Steueranweisung, und der Browser ignoriert diese oder zumindest die Attribute, welche er nicht versteht. Im schlimmsten Fall werden Informationen unterdrückt oder Teile einer Steueranweisung als Klartext im Browser ausgegeben. Nicht schön, aber nicht schlimm. Eine fehlerhafte HTML-Struktur kann durchaus noch sinnvoll genutzt werden.

JavaScript ist da schon gefährlicher. JavaScript ist nicht so fehlertolerant wie HTML und kann es auch nicht sein. Falls Ihr Script also einen Fehler hat, müssen Sie ihn finden, bevor die Seite ausgeliefert werden kann. Grundsätzlich muss man aber beachten, dass jeder Korrekturversuch eines Fehlers in einem Programm/Script die Gefahr neuer - meist noch schlimmerer - Fehler nach sich zieht. Die gleiche Gefahr droht, wenn man ein funktionierendes Programm oder Script optimieren will. Es ist gängige Erfahrung, dass jedes Programm/Script soweit optimiert wird, bis es unbrauchbar ist! Dabei folgt in der Regel als Krönung, dass jedes zur Unbrauchbarkeit optimierte oder bezüglich Fehler »verschlimmbesserte« Programm/Script sich unmöglich in den Zustand zurückversetzen lässt, wo es noch lauffähig war oder zumindest nicht so extrem verhunzt!

Bei solchen Fehlern muss man verschiedene Situationen unterscheiden. Es gibt einmal typographische Fehler beim Schreiben des Scripts. Wenn Sie sich beim Schreiben des Quelltexts einfach vertippt und ein Schlüsselwort, eine Variable oder sonst etwas Entscheidendes falsch geschrieben haben, können zwei Fälle auftreten.

Sofern Sie ein Wort absolut falsch geschrieben haben, ist die Situation oft leicht in den Griff zu bekommen. In dem Fall haben Sie nicht zufällig einen solchen Schreibfehler gemacht, sodass der falsche Begriff wieder einen sinnvollen Begriff und keinen syntaktischen Widerspruch ergibt (was der zweite und viel schlimmere Fall ist). Nehmen wir ein Beispiel aus der Textverarbeitung. Sie wollten beispielsweise Kirsche schreiben und haben Kirche getippt - ein ebenfalls sinnvolles Wort. Das Rechtschreibprogramm der Textverarbeitung hätte keine Chance, diesen typographischen Fehler zu finden. Auch Sie haben in JavaScript dann nur die Möglichkeit, den Fehler im Quelltext durch aufmerksames Lesen oder Analyse des Resultates von dem Script zu lokalisieren. Etwa wird die Syntax

summe = a - b;

durchaus funktionieren. Der Programmcode wird nur nicht das tun, was er tun soll.

Wenn Sie jedoch einen Schreibfehler haben, der keinen vernünftigen Ausdruck ergibt, sind Sie (obwohl es erst einmal schlimmer aussieht) meist in der besseren Situation. Der Ausdruck wird in der Regel einen syntaktischen Widerspruch innerhalb der Programmiersprache erzeugen, und der Interpreter wird bei seiner Arbeit den Fehler entdecken. Danach reagiert der Interpreter mit Abbruch der Verarbeitung und gibt eine Information zurück, wie Sie den Fehler finden können (gleich mehr dazu).

Einer der heimtückischsten typographischen Fehler unter JavaScript ist die Nichtbeachtung von Groß- und Kleinschreibung.

Ein weiterer eng verwandter Fehlertyp ist der syntaktische Fehler. Dies sind Fehler bei der Verwendung der Programmiersprachensyntax. Viele syntaktische Fehler beruhen auf typographischen Fehlern, aber beileibe nicht alle. Syntaktische Fehler haben den Vorteil, dass der Interpreter (oder der Compiler im Compilerfall) diese Regelverletzung recht gut erkennen kann und meist gute Hilfestellung zum Lokalisieren anbietet. Viele syntaktische Fehler beruhen darauf, dass

An dieser Stelle hilft es auch gewaltig, wenn ein Editor Syntaxhighlighting beherrscht (siehe dazu Tag 1).

Gefährliche Programmfehler sind diese, welche erst zur Laufzeit auftreten und die auf logische Fehler im Programmaufbau zurückzuführen sind. Hierbei handelt es sich meist um ein syntaktisch vollkommen korrektes Script, das aber Fehler zur Laufzeit zulässt. Dies geschieht am häufigsten, wenn eine Variable zur Laufzeit einen falschen Wert zugeordnet bekommt. In eine ähnliche Kategorie fallen Programmfehler zur Laufzeit, welche auf äußeren Umständen (Situationen, die erst zur Laufzeit entstehen, die Umgebung des Programms oder den Anwender) beruhen. Diese Fehlerkonstellation kann durch verschiedene Dinge entstehen. Etwa wird in einer Webseite eine bestimmte Schriftart vorausgesetzt, die auf der Plattform des Anwenders nicht vorhanden ist. Unter HTML nur ärgerlich, in einem Script oder Programm unter Umständen bereits ein ernstes Problem. Oder ein Script lässt Anwendungsfehler durch den User zu. Dies sind also Fehler, die auf konzeptioneller Seite zu suchen sind. Während der Planung eines Programms oder Scripts muss dies einkalkuliert werden1.

Das Auffinden und die Beseitigung der typographischen und syntaktischen Fehler sowie der logischen Laufzeitfehler ist das, was man unter Debugging versteht. Der Begriff Debugging geht auf das englische Wort Bug zurück, was übersetzt Wanze bzw. Käfer bedeutet. Es gibt einige Anekdoten, woher der Name kommt. Die bekannteste Anekdote hat zum Inhalt, dass in frühen EDV-Zeiten in einem Röhrengroßrechner ein Programmfehler die damaligen Entwickler zur Verzweiflung getrieben haben soll. Der Fehler zur Laufzeit war absolut unlogisch, da im Quelltext kein Fehler zu finden war. Die Lösung fand sich erst, als man den Rechner selbst auseinander schraubte und zwischen den Röhren eine tote Wanze fand, die mit ihrem Körper Schaltkreise störte. Wenn man heute von einem Hilfsprogramm redet, das zum Auffinden von Fehlern in Programmen genutzt wird, redet man von einem Debugger.

Fehler im Vorfeld vermeiden

Um Fehler bei der Erstellung einer HTML-Seite, eines Scripts oder eines Programms bereits im Vorfeld zu minimieren, hilft eine sorgfältige Vorbereitung. Dies umfasst beispielsweise folgende Punkte:

Insbesondere machen Anfänger und Hobbyprogrammierer den Fehler, die Programmplanung und Konzeption zu vergessen. Dabei ist gerade dieser Punkt im Zyklus der Programmerstellung der entscheidende (insbesondere, um logische Fehler zu vermeiden und spätere - sehr fehlerträchtige - Umstrukturierungen zu vermeiden). In professionellen Projekten nimmt dies Phase mindestens 30% der geplanten Zeit ein2. Gerade Leute, die nicht genügend Disziplin aufbringen, um in der Anfangsphase eines Webauftritts den Computer einen guten Mann sein zu lassen und sich Gedanken um das geplante Konzept zu machen, sollten in diesem Stadium den Computer gar nicht erst anschalten. Ein paar Blatt Papier und Ruhe sind in dieser Phase dann bessere Werkzeuge als der Computer, der zum einfach Losprogrammieren und Spielen verleitet. In der konkreten Programmierphase hilft dann natürlich vor allem die sorgfältige und konzentrierte Eingabe.

Sicherungsmaßnahmen

Trotz der gerade beschriebenen Maßnahmen lassen sich Fehler nie ganz vermeiden. Dabei muss man sich verdeutlichen, dass man ja immer von einem Stand aus weiterentwickelt, wo ein Script läuft (außer direkt bei Beginn). Oft kommt man auch in die Situation, dass ein fast fertiges und lauffähiges Script noch mal schnell erweitert oder verändert wird. Meist werden dann mehrere Änderungen vor dem nächsten Test durchgeführt, und prompt hat man einen Fehler. Leider ist es so, dass man sich normalerweise nicht jede Änderung merken kann (obwohl dies - oder noch besser eine Dokumentation - sinnvoll wäre). Oft kann diese Veränderung seit dem letzten lauffähigen Stand dann nicht mehr rückgängig gemacht werden. Hat man dann den letzten lauffähigen Stand nicht gesichert, bleibt oft nur ein aufwendiges Try-and-Error-Verfahren, um etwas wiederherzustellen, was man schon einmal hatte. Es gibt deshalb die unbedingte Regel, jede lauffähige und bereits halbwegs richtige Scriptversion zu sichern und die Erweiterung in einem anderen Verzeichnis oder unter einem neuen Namen zu speichern. Im Abschnitt über Optimierung werden wir dies durchspielen. Dazu kommen natürlich die - hoffentlich - selbstverständlichen regelmäßigen Sicherungen aller wichtiger Daten außerhalb des Arbeitsrechners (auf CDs, ZIP-Disketten, Disketten, Bändern, Servern usw.).

Konkrete Fehlerbehandlung

Wenn nun ein Fehler aufgetreten ist und sich der fehlerfreie Zustand nicht reproduzieren lässt oder sonst nicht gewünscht ist, bleibt nur die Fehlerbeseitung. Dabei stellt sich zuerst das Problem, den Fehler überhaupt zu lokalisieren. Dies kann mit einem Debugger geschehen, aber auch ohne ein solches Tool. Gerade unter JavaScript werden wir ohne Debugger arbeiten. Dazu gibt es gewisse Standardtechniken.

Hilfe durch den JavaScript-Interpreter

Da gibt es einmal die Hilfe durch den JavaScript-Interpreter im Browser, der bei syntaktischen Fehlern in einem Script die Abarbeitung unterbrechen wird. Dabei ist es jedem Browser überlassen, wie er dann weiter verfährt. Wenn ein JavaScript bei der Ausführung einen Fehler aufweist, wird der Internet Explorer bei entsprechender Einstellung automatisch ein Fehlerfenster öffnen und die Zeile mit dem Fehler sowie einen Grund für den Fehler angeben. Wenn das Fehlerfenster nicht automatisch aufgeblendet wird, wird links unten in der Statuszeile ein Symbol erscheinen, auf das Sie doppelklicken können, um das Fehlerfenster zu aktivieren.

Abbildung 7.1:  Das Fehlerfenster des Internet Explorer

Abbildung 7.2:  In der Statuszeile kann über das Symbol links per Doppelklick das Fehlerfenster aktiviert werden

Der Netscape Navigator hält bei einem Fehler in einem Script die Ausführung an und zeigt erst einmal keine weiteren Informationen an.

Abbildung 7.3:  Keine Fehlermeldung im Navigator. Das Script wird einfach nicht ausgeführt

Um diese zu bekommen, müssen Sie in der Adresszeile des Browsers javascript: eingeben (der Doppelpunkt gehört unbedingt dazu).

Abbildung 7.4:  Fehlerinformationen anzeigen im Navigator

Daraufhin öffnet sich ein zusätzliches Communicator-Fenster, in dem Sie die Zeile mit dem Fehler plus einer Beschreibung für den Fehler finden.

Abbildung 7.5:  Das Fehlerfenster des Navigator

Leider gilt bei allen Adress- und Fehlerangaben, dass weder die Adresse stimmen muss noch der angemerkte Fehlertyp wirklich richtig ist. Falls Sie direkt an der angegebenen Adressangabe den Fehler finden, haben Sie einfach Glück, denn diese Adressangabe ist nur die Stelle, wo sich ein Fehler auswirkt und nicht unbedingt der Entstehungsort. Dies muss und wird nicht immer identisch sein, aber zumindest ist der Fehler schon einmal eingegrenzt. Definitiv kann man aber dann sagen, dass der Fehler irgendwo davor im Quelltext zu finden ist. Der Fehlertyp kann deshalb falsch sein, weil ein Fehler sich erst an einer späteren Stelle auswirkt und dann eine andere Situation bewirkt. Sie können dies mit dem nachfolgenden kleinen Beispiel testen, in dem ein winziger, aber extrem tückischer Fehler eingebaut ist.

Starten Sie einen Editor und geben sie dort den nachfolgenden Quelltext ein (beachten Sie bitte unbedingt Groß- und Kleinschreibung):

<html>
<body>
<SCRIPT LANGUAGE="JavaScript">
var pw = prompt("Bitte geben Sie Ihre Spende ein","");
If(pw < 5000)
{
document.write("<H1 align=center>Geizhals</H1>");
document.write("<br>");
}
else if(pw < 10000)
{
document.write("<H1 align=center>Vielen Dank</H1>");
document.write("<br>");
}
else
{
document.write(
"<H1 align=center>Vielen, vielen Dank</H1>");
document.write("<br>");
}
</SCRIPT>
</body>
</html>

Starten Sie die Datei in dem Netscape Navigator. Der Navigator wird nur eine leere Seite anzeigen. Wenn Sie dann mit JavaScript: das Fehlerfenster aufblenden, wird er die Zeile 10 und dort das Schlüsselwort else »anmosern«.

Abbildung 7.6:  Das else in Zeile 10 wird vom Navigator moniert

Das ist aber nicht der Fehler. Haben Sie ihn entdeckt? Öffnen Sie auf jeden Fall erneut die Datei im Internet Explorer. Auch dort erscheint nur eine leere Seite und das Fehlerfenster enthält analog die Zeile 10 als Fehlerposition.

Abbildung 7.7:  Auch der Internet Explorer gibt Zeile 10 als Fehlerposition an

Wo ist aber wirklich der Fehler? Die Sache ist wirklich heimtückisch - das if in Zeile 6 ist im Beispiel mit großem I geschrieben. Damit gibt es für den Interpreter ein else ohne vorangestelltes if und das ist eine falsche Syntax. Die ungewöhnliche Mischung von Groß- und Kleinschreibung bei den restlichen Worten im Quelltext sollte nur die Fehlerquelle verschleiern und die Sache für Sie etwas schwieriger machen.

Fehlerlokalisation mit Kontrollausgaben

Der klassische Weg, um Fehler zu finden, sind Kontrollausgaben, welche im endgültigen Source dann beseitigt werden. Gängige Praxis ist, vor einem vermuteten Fehler eine Bildschirmausgabe der »Wanze« (also der Variablen, in der man die Fehlerursache vermutet) zu erzeugen. Dies könnte so aussehen (die Variable meinWert ist die vermutete Wanze):

// Debuggausgabe
document.write("Kontrollpunkt 1: ", meinWert);
// vermutete Fehlerstelle
meinWert=funktionMitRueckgabeWert();

Vor der Entstehung des Laufzeitfehlers sehen Sie auf dem Bildschirm den Wert der Variablen. Sie können selbstverständlich an den unterschiedlichsten Stellen im Programm solche Debug-Ausgaben einfügen, um eine Variable über mehrere Schritte hinweg zu verfolgen.

Einsatz von Editoren mit farblicher Kennung von Syntaxelementen

Insbesondere im Fehlerfall macht der Einsatz von Editoren Sinn, die verschiedenartige Syntaxelemente farblich unterschiedlich kennzeichnen. Insbesondere kann eine solche farbliche Darstellung von Bereichen den Anfang des kritischen Bereichs deutlich machen. Dazu muss aber selbstverständlich der Editor die Schlüsselworte der verwendeten Sprache kennen. Wir haben dazu ja am ersten Tag zwei schöne Programme kurz vorgestellt. Phase 5 kann beispielsweise auf Syntaxhighlighting für JavaScript eingestellt werden.

Abbildung 7.8:  Deutlich wird If in der falschen Schreibweise nicht als Schlüsselwort dargestellt.

Sinnvolle Schritte zu Lokalisierung von Fehlern

Grundsätzlich sollten Sie im Fehlerfall die Informationen nutzen, die Ihnen der Interpreter liefert. Falls dies aber nicht ausreicht, die Macken zu lokalisieren, gibt es einige Tricks, Fehler dennoch zu finden. Die Erfahrung zeigt, dass es einige genau zu benennende Situationen gibt, auf die besonders geachtet werden sollte:

Optimierung von Webseiten und Scripten

Wenn man eine HTML-Seite oder ein Script erstellt oder allgemein programmiert, kommt man irgendwann an die Stelle, wo eine Webseite so aussieht wie gewünscht bzw. ein Script oder Programm - soweit man es erkennen kann - fehlerfrei läuft, aber noch verschiedene Wünsche offen bleiben. Dann führt man - wenn Zeit bleibt - eine Aktion durch, die Optimierung genannt wird. Dies kann in mehreren Richtungen verstanden werden.

Man kann ein HTML-Dokument, ein Script oder ein Programm bezüglich seiner Funktionalität, seiner optischen Gestaltung oder seiner Bedienerfreundlichkeit optimieren. Dies sind dann Verbesserungen, die offensichtlich sind, wenn man die Vorgängerversion betrachtet oder sie im Vergleich zur verbesserten Variante bedient. Das wollen wir hier nicht (!) intensiv verfolgen. Da gibt es zu viele unterschiedliche Ansätze, als dass dies so allgemein besprochen werden kann. Am besten verfolgt man solche Optimierungen, indem man bisher unbeteiligte Testpersonen (die der potentiellen Zielgruppe zuzuordnen sind) hinzuzieht und deren Eindrücke und Vorschläge als Ansatz nimmt. Aber auch der eigenen Phantasie sind da keine Grenzen gesetzt.

Wir wollen hier eine Optimierung ansprechen, welche eine Webseite effektiver macht bezüglich

Letzteres bedeutet, dass es nicht jedem so einfach gemacht werden soll, Ihren ausgefeilten Quelltext zu analysieren und dann für sich weiter zu verwenden.

Diese mehr im Hintergrund laufenden Optimierungen werden vom Anwender normalerweise eher unterbewusst wahrgenommen3, sind aber dennoch sehr wichtig. Dabei muss beachtet werden, dass die angesprochenen Punkte sich teilweise ausschließen und man meist einen Kompromiss finden muss. Insbesondere schließen sich Wartbarkeit und Reduzierung der Größe ab einer gewissen Optimierung in Hinsicht der Dateigröße aus.

Erste und effektivste Maßnahme zum Optimieren eines Webprojekts ist natürlich, Grafiken und andere große Dateitypen zu verkleinern. Das beinhaltet, das geeignetste Dateiformat zu testen, die Farbtiefe und Bildgröße zu perfektionieren, bei Animationen die Framerate so niedrig wie möglich einzustellen, die Tonqualität bei Sounds soweit wie möglich zu reduzieren etc. Diese Maßnahmen sollten natürlich auf jeden Fall und mit den entsprechenden Programmen erfolgen - wir wollen hier nachfolgend aber die Maßnahmen vorantreiben, die auf Textseite möglich sind4.

Um was geht es bei der Optimierung der Übertragungszeit und Größe bzw. der Verbesserung der Wartbarkeit? Nun, wir wollen den gesamten Ablauf mit einem Beispiel verbinden, an dem wir einen typischen Optimierungvorgang sehen werden. Erstellen Sie als Erstes die nachfolgende einfache Webseite mit einem kleinen JavaScript (Dateiname Einkauf.html):

<HTML>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
/* Variablendeklaration */
// Die Preise der Produkte - fest vorbelegte DM-Beträge
var preisProduktA = 31.82;
var preisProduktB = 2.94;
var preisProduktC = 4.22;
// Deklaration der Variablen für die Menge des
// jeweiligen Produktes
var anzahlProduktA;
var anzahlProduktB;
var anzahlProduktC;
// Summe der Gesamtbestellung
var gesamtSumme;
/* Eingabe der Anzahl für jedes Produkt */
anzahlProduktA = prompt("Anzahl Hosen","");
anzahlProduktB = prompt("Anzahl Socken","");
anzahlProduktC = prompt("Anzahl T-Shirts","");
/* Berechnung der Gesamtsumme */
gesamtSumme =
  anzahlProduktA * preisProduktA +
  anzahlProduktB * preisProduktB +
  anzahlProduktC * preisProduktC;
/* Ausgabe */
document.write("<H1 align=center>Sie haben folgende Produkte bestellt:</H1>");
// Hosen
document.write(
    "Hosen: ",
    anzahlProduktA ,
    " Stücke a einem Einzelpreis von DM ",
    preisProduktA ,
    " = DM ",
    anzahlProduktA * preisProduktA,
    " gesamt.");
document.write("<br>");
// Socken
document.write(
    "Socken: ",
    anzahlProduktB ,
    " Stücke a einem Einzelpreis von DM ",
    preisProduktB ,
    " = DM ",
    anzahlProduktB * preisProduktB,
    " gesamt.");
document.write("<br>");
// T-Shirts
document.write(
    "T-Shirts: ",
    anzahlProduktC ,
    " Stücke a einem Einzelpreis von DM ",
    preisProduktC ,
    " = DM ",
    anzahlProduktC * preisProduktC,
    " gesamt.");
document.write("<P>");
// Gesamtsumme
document.write(
    "<H3>Gesamtsumme DM ",
    gesamtSumme ,
    ".</H3>");
document.write("<br>");
</SCRIPT>
</BODY>
</HTML>

Wir erstellen hier eine Art Warenkorbsystem (ganz ohne Formulare als Eingabemöglichkeit und einfachster Bauart - es geht nicht um eine Praxisfähigkeit). Das Beispiel wird beim Laden der Webseite ausgeführt und fragt mit drei aufeinander folgenden Eingabemasken die Anzahl der Produkte ab, die ein Anwender von jedem dieser Produkte kaufen möchte.

Abbildung 7.9:  Letzte Eingabe ist die Anzahl des dritten Produktes

Abbildung 7.10:  Die Anzahl des zweiten Produktes

Abbildung 7.11:  Die Anzahl des ersten Produktes

Jedes der Produkte hat einen vordefinierten Preis (jeweils in einer Variablen im Quelltext gespeichert - preisProduktA, preisProduktB, preisProduktC), der dann mit der jeweiligen Anzahl (ebenfalls jeweils in einer weiteren Variablen gespeichert - anzahlProduktA, anzahlProduktB, anzahlProduktC) zu multiplizieren ist.

Daraus wird dann eine Gesamtsumme errechnet, die ebenso in einer Variablen gespeichert wird (gesamtSumme). Die Webseite selbst wird mit diesen Informationen dynamisch geschrieben (Ausgabe des jeweiligen Artikels und der Einzelpreise, der jeweiligen Einzelpreise mal der individuellen Anzahl und die Gesamtsumme der Bestellung). Soweit funktioniert das Beispiel in der notierten ersten Version. Das werden Sie sehen, wenn Sie es in einen Browser laden und vernünftige Zahlenwerte eingeben (beachten Sie bitte, dass Rundungsungenauigkeiten und Falscheingaben nicht abgefangen werden - das soll hier keine Rolle spielen). Beachten Sie, dass das Script im Quelltext ausführlich dokumentiert ist.

Abbildung 7.12:  Die Ausgabe mit den berechneten Werten

Der Quelltext ist jedoch wirklich nicht optimal. Es bieten sich zahlreiche Stellen für eine Verbesserung an. Zur Optimierung kommen beispielsweise folgende Details in Betracht:

  1. Die Variablenbezeichner. Diese können entweder mit sprechenderen Bezeichnern gewählt werden oder aber verkürzt, um die Webseite zu verkleinern.
  2. Sich wiederholende Passagen im Script könnten in Variablen gespeichert werden, um damit das Script kleiner und besser wartbar zu machen. Insbesondere lassen sich dann Änderungen und Wartungen leichter durchführen, weil nur an einer zentralen Stelle geändert werden muss. Die Verwendung von Textbausteinen für sich wiederholende Textpassagen, die Variablen zugeordnet werden, verkleinert das Script merklich.
  3. Zusammenfassen von Codestrukturen, welche dadurch kürzer werden. Dies kann sowohl Deklarationen betreffen, aber auch Aufrufe von Methoden und ähnliche Situationen.
  4. Entfernen sämtlicher Kommentare.

Warum macht man sich eigentlich diese Mühe mit der Optimierung des Quelltextes? Nun, jedes Zeichen, das im Quelltext vorkommt, muss auch in den Speicher des Anwenderrechners geladen werden. Bei Netzwerken und insbesondere dem Spezialfall des Internets muss jedes Zeichen zudem noch über die (langsamen Internet-) Leitungen übertragen werden. Wenn sich mit den genannten Optimierungen das Script erheblich verkleinern lässt, hat dies die Folge, dass eine Webseite auch schneller beim Anwender in den Browser geladen wird. Zwar werden Buchstaben im Verhältnis zu Grafiken oder anderen Multimediaformaten nicht so stark ins Gewicht fallen, aber eine Rolle kann dies - gerade bei großen Seiten - schon spielen.

Die nachfolgenden Schritte zur Optimierung des Quelltexts haben ab einer gewissen Grenze zugleich den oft nicht unerwünschten Nebeneffekt, dass ihr Script immer schlechter zu lesen ist (das werden Sie gleich sehen). Dabei ist (was das »nicht unerwünscht« angeht) an die Leute gedacht, die eine interessante Seite im Web sehen und einfach kopieren oder geringfügig an ihre Bedürfnisse anpassen. Man sollte sich nichts vormachen - die Beachtung des geistigen Eigentums und des Urheberrechts ist im Internet nicht sonderlich ausgeprägt - gelinde ausgedrückt5. Die Optimierung verändert dabei in keinster Weise die Funktionalität des Scripts - wenn Sie keine Fehler einbauen. Sie macht nur den Raben das Stibitzen etwas unbequemer.

Für Sie selbst ist es jedoch unbedingt notwendig, dass Sie irgendwie dokumentieren, was Sie beim Optimieren alles machen und wie Sie gegebenenfalls die Datei warten oder verändern können. Das sollte am besten in einer zusätzlichen Dokumentation geschehen.

Wie gehen Sie nun am besten vor? Das Beispiel ist bisher so aufgebaut, dass es fehlerfrei läuft und all das tut, was das Script auch endgültig tun soll. Auch ist es gut lesbar und ausreichend im Quelltext dokumentiert. Auf diese Weise ein Script erst einmal zu erstellen und lauffähig zu machen, ist sehr sinnvoll. Als erstes sollte dieser Stand eingefroren werden. Das bedeutet, diese Version ihres Scripts wird nicht mehr verändert, bevor nicht irgendwo eine Kopie gespeichert ist. Dann erst wird mit der Datei weitergearbeitet und perfektioniert. So eine permanente Sicherung eines bis dahin fehlerfreien Standes sollten Sie auf jeden Fall anlegen (siehe die Bemerkungen zu Fehler und Debuggen am Anfang des Kapitels). Wir erstellen nun eine Kopie und wollen die Datei einfach umbenennen in Einkauf.001. Danach vervollkommnen wir die Variablenbezeichner - sowohl in Bezug auf die Größe als auch die Lesbarkeit.

Die Webseite ist in ihrer nicht optimierten Form genau 1625 Byte groß. Dies sollte als Startwert festgehalten werden. Sie können die genaue Größe einer Datei überprüfen, indem Sie diese mit der rechten Maustaste anklicken und Eigenschaften aus dem Kontextmenü auswählen.

Bei den Variablenbezeichnern muss man einen Kompromiss zwischen Eindeutigkeit, möglichst wenig Zeichen und halbwegs vernünftiger Lesbarkeit eingehen. Ein einzelner Buchstabe ist kaum sinnvoll, denn das ist dann auch für Sie kaum noch wartbar (selbst wenn man im Web den Kiebitzen den Spass verderben möchte) - außerdem kann es vorkommen, dass die Buchstaben des Alphabets nicht reichen. Variablen mit einer Länge von einem Buchstaben werden meist nur für Zählvariablen in Schleifen verwendet.

Mit einer Verkürzung der Variablenbezeichner auf zwei bis drei Buchstaben für die in dem Beispiel gewählten Variablen hat man wahrscheinlich den besten Kompromiss gefunden. Wir wollen folgende Ersetzungen vornehmen (so oder so ähnlich könnten Sie das dann auch in der Praxis dokumentieren):

preisProduktA - pHo (steht für preisHosen)

preisProduktB - pSo (steht für preisSocken)

preisProduktC - pTs (steht für preisT-Shirts)

anzahlProduktA - aHo (steht für anzahlHosen)

anzahlProduktB - aSo (steht für anzahlSocken)

anzahlProduktC - aTs (steht für anzahlT-Shirts)

gesamtSumme - gS (steht für gesamtSumme)

Wenn dies so in einer separaten Dokumentation festgehalten wird, sollte die Aktion sowohl die Dateigröße reduzieren als auch die Wartbarkeit und sogar die Lesbarkeit verbessern.

Ersetzen Sie Bezeichner - wenn es geht - nicht von Hand. Nutzen Sie die »Replace«-Funktionalität Ihres Editor, sofern Sie eine entsprechende Funktion dort haben. Ansonsten gehen Ihnen unter Umständen Bezeichner durch die Lappen und dann entstehen Fehler, die vollkommen überflüssig sind. Beachten Sie aber, dass Sie bei »Replace-all« unter Umständen auch Gefahren ausgesetzt sind. Am besten aktivieren Sie, dass nur ganze Wörter ausgetauscht werden und dabei Groß- und Kleinschreibung beachtet wird.

Nach dieser Optimierung sieht das Script so aus:

<HTML>
<BODY>
<SCRIPT LANGUAGE="JavaScript">
/* Variablendeklaration */
// Die Preise der Produkte - fest vorbelegte DM-Beträge
var pHo = 31.82;
var pSo = 2.94;
var pTs = 4.22;
// Deklaration der Variablen für die Menge des
// jeweiligen Produktes
var aHo;
var aSo;
var aTs;
// Summe der Gesamtbestellung
var gS;
/* Eingabe der Anzahl für jedes Produkt */
aHo = prompt("Anzahl Hosen","");
aSo = prompt("Anzahl Socken","");
aTs = prompt("Anzahl T-Shirts","");
/* Berechnung der Gesamtsumme */
gS =
  aHo * pHo +
  aSo * pSo +
  aTs * pTs;
/* Ausgabe */
document.write("<H1 align=center>Sie haben folgende Produkte bestellt:</H1>");
// Hosen
document.write(
    "Hosen: ",
    aHo ,
    " Stücke a einem Einzelpreis von DM ",
    pHo ,
    " = DM ",
    aHo * pHo,
    " gesamt.");
document.write("<br>");
// Socken
document.write(
    "Socken: ",
    aSo ,
    " Stücke a einem Einzelpreis von DM ",
    pSo ,
    " = DM ",
    aSo * pSo,
    " gesamt.");
document.write("<br>");
// T-Shirts
document.write(
    "T-Shirts: ",
    aTs ,
    " Stücke a einem Einzelpreis von DM ",
    pTs ,
    " = DM ",
    aTs * pTs,
    " gesamt.");
document.write("<P>");
// Gesamtsumme
document.write(
    "<H3>Gesamtsumme DM ",
    gS ,
    ".</H3>");
document.write("<br>");
</SCRIPT>
</BODY>
</HTML>

Die Datei ist jetzt nur noch 1313 Byte groß - wir haben bereits ein Viertel der Zeichen »wegoptimiert«. Speichern Sie diesen Stand unter Einkauf.002, nachdem Sie die Funktionalität der Webseite überprüft haben. Die Vorgängerdatei sollte dennoch beibehalten werden - vielleicht muss man nochmals darauf zurückgreifen. Sie ist auf jeden Fall eine gute Dokumentation. Wir entfernen nur die Kommentare - das reduziert die Geschichte bereits auf 980 Byte (Stand anschließend einfrieren unter Einkauf.003). Allerdings geht dieser Schritt bereits zu Lasten einer späteren Wartung.

Der nächste Schritt fasst Code zusammen, der ohne Funktionalitätsverlust verkürzt werden kann. Die Zeilen

var aHo;
var aSo;
var aTs;
var gS;

können zu

var aHo,aSo,aTs,gS;

zusammengefasst werden. Das bringt 18 Byte. Wir wollen aber in diesem Schritt noch weiter gehen. Beachten Sie, dass auch Leerzeichen, die nur zur Übersichtlichkeit eingefügt werden, in Klartextdateien jeweils ein Byte benötigen. Aber auch Zeilenvorschübe und Tabulatoren, die Quelltext nur übersichtlicher machen, sind effektive Bytes in der Webseite, die mit übertragen werden müssen (das gilt auch für reine HTML-Dateien).

An der Stelle müssen wir uns entscheiden, ob wir die Wartbarkeit oder die Optimierung in Hinsicht der Größe priorisieren wollen. Im Web ist Dateigröße sehr wichtig und wir wollen - auch auf Kosten der Wartbarkeit - diese perfektionieren. Wenn der Code sowieso nicht gut lesbar sein muss, kann auch auf diese Trennzeichen verzichtet werden. Die Eliminierung von überflüssigen Leerzeichen, Tabulatoren und Zeilenumbrüchen bringt (wenn einige wenige Zeilenumbrüche vorerst erhalten bleiben) eine Reduktion auf 799 Byte. Abermals zur Betonung - ohne die geringste Beeinflussung der Funktionalität. Das Script (Dateiname Einkauf.005) sieht jetzt so aus (wobei beim Lesen im Buch satztechnische Zeilenumbrüche und Leerzeichen berücksichtigt werden müssen):

<HTML><BODY><SCRIPT LANGUAGE="JavaScript">
var pHo = 31.82;var pSo=2.94;var pTs=4.22;var aHo,aSo,aTs,gS;aHo = prompt("Anzahl Hosen","");aSo = prompt("Anzahl Socken","");aTs = prompt("Anzahl T-Shirts","");
gS=aHo*pHo+aSo*pSo+aTs*pTs;
document.write("<H1 align=center>Sie haben folgende Produkte bestellt:</H1>");
document.write("Hosen: ",aHo," Stücke a einem Einzelpreis von DM ",pHo," = DM ",aHo*pHo," gesamt.");
document.write("<br>");
document.write("Socken: ",aSo," Stücke a einem Einzelpreis von DM ",pSo," = DM ",aSo*pSo," gesamt.");
document.write("<br>");
document.write("T-Shirts: ",aTs," Stücke a einem Einzelpreis von DM ",pTs," =DM ",aTs*pTs," gesamt.");
document.write("<P>");
document.write("<H3>Gesamtsumme DM ",gS,".</H3>");
document.write("<br>");
</SCRIPT></BODY></HTML>

Nun sollen alle mehrfach verwendeten Textpassagen durch Textbausteine in Variablen abgelegt werden. Folgende Ersetzungen sind sinnvoll:

" Stücke a einem Einzelpreis von DM "                      -  sDM
" gesamt."              -  gsa

Dies sinnvoll - d.h. ohne Zeilenvorschub - in den Quelltext notiert, reduziert die Datei auf 741 Byte (Stand Einkauf.006). Wenn wir nun noch JavaScript bezüglich der losen Typisierung ausnutzen und auf das Schlüsselwort var bei der Variablendeklaration verzichten und die Variablen aHo, aSo und aTs erst bei der Wertzuweisung der prompt()-Funktion erzeugen, bekommen wir die Größe der Datei (Stand Einkauf.007) auf 702 Byte.

Unsere letzten - nochmals sehr effektiven - Optimierungsmaßnahmen bestehen darin, auf die mehrfache Verwendung von document.write() zu verzichten und per Kommata getrennt nur noch eine solche Anweisung zu verwenden. Dazu eliminieren wir die letzten Zeilenumbrüche. Dies beides bringt erneut eine Menge und reduziert unsere Abschlussdatei auf nunmehr nur 550 Byte. Obwohl immer noch geringfügig mehr Luft drin ist, wollen wir es dabei bewenden lassen und uns die Datei Einkauf.008 abschließend anschauen (Zeilenumbrüche und scheinbare Leerzeichen außerhalb der Strings sind nur satztechnisch im Buch notwendig):

<HTML><BODY><SCRIPT LANGUAGE="JavaScript">pHo=31.82;pSo=2.94;pTs=4.22;aHo = prompt("Anzahl Hosen","");aSo = prompt("Anzahl Socken","");aTs = prompt("Anzahl T-Shirts","");sDM=" Stücke a einem Einzelpreis von DM ";gsa=" gesamt.";gS=aHo*pHo+aSo*pSo+aTs*pTs;document.write("<H1 align=center>Sie haben folgende Produkte bestellt:</H1>","Hosen: ",aHo,sDM,pHo," = DM ",aHo*pHo,gsa,"<br>","Socken: ",aSo,sDM,pSo," = DM ",aSo*pSo,gsa,"<br>","T-Shirts: ",aTs,sDM,pTs," =DM ",aTs*pTs,gsa,"<P>","<H3>Gesamtsumme DM ",gS,".</H3>","<br>");</SCRIPT></BODY></HTML>

Die Webseite wurde ohne irgendeine Beeinträchtigung der Funktionalität von 1625 Byte auf ein Drittel der Ursprungsgröße verkleinert. Dies bedeutet auch, dass die Seite bei einer konstanten Übertragungsgeschwindigkeit im Netz in einem Drittel der Zeit da ist. Was dies bei größeren Seiten für Optimierungsmöglichkeiten eröffnet, wird sicher klar sein.

Lesbar ist so ein Quelltext dann nicht mehr sonderlich gut, was aber wie gesagt oft auch gewünscht ist. Ob Sie eine Webseite aber wirklich so stark optimieren müssen, das sei dahin gestellt. Wir wollten hier nur die Machbarkeit zeigen. Sie müssen entscheiden, was für Sie noch sinnvoll ist und welche der Optimierungsmaßnahmen Sie bei Bedarf auswählen.

Abbildung 7.13:  Das Kompressionstool von  1 Page 2000

Optimierungen müssen auch nicht unbedingt mit der Hand erfolgen. Insbesondere wenn es um die Optimierung von den reinen HTML- Passagen innerhalb der Webseite geht. Einige HTML-Tools beinhalten Kompressions-Features. So auch der Editor 1st Page 2000, den wir am ersten Tag kurz vorgestellt haben. Eine Optimierung von den HTML- Passagen in einer Webseite ist besonders dann angeraten, wenn solche HTML-Tools zum Erstellen der Seite erstellt wurden, wo der Anwender wenig oder keinen direkten Einfluss auf den erzeugten Quelltext hat.

Wenn wir den ursprünglichen Quelltext durch den Komprimierungsalgorithmus von 1st Page 2000 laufen lassen, kommt ein 1615 Byte großer Source heraus. Keine allzu starke Optimierung, aber man muss der Fairness halber zugestehen, dass die Optimierungen von dem Tool schlechte HTML-Anweisungen verbessern, die im Original schon gar nicht verwendet wurden. Das Tool optimiert Seiten, indem statt langer HTML-Anweisungen identisch wirkende, aber kürzer zu schreibende Anweisungen genommen werden - etwa <B> statt <STRONG> oder der <CENTER>-Tag statt <P align=center>. Dazu wird speziell die Frontpage- Eigenwerbung eliminiert. Die anderen Schritte wie das Löschen von überflüssigen Kommata, Leerzeichen und Returns entspricht unseren manuellen Maßnahmen, nur lässt das Kompressionstool alle Script- Bereiche unberührt, wo wir ja unsere Hauptersparnis erreicht haben.

Wir wollen noch eine weitere Optimierungsmaßnahme durchführen (diesmal ohne Scripte). In diesem Fall lassen wir zwei Programme gegeneinander »kämpfen«. Eine Tabelle, welche mit Excel 2000 erstellt wird, soll als Webseite gespeichert werden. Danach kontrollieren wir die Dateigröße, betrachten den Quelltext und versuchen, mit dem HTML- Editor 1st Page 2000 diese Seite zu optimieren. Das »Kampf« ist deshalb brutal, weil Office-Programme fürchterlichen HTML-Code erzeugen (in Bezug auf Kompatibilität und vor allem Dateigröße).

Abbildung 7.14:  Die zu speichernde Exceldatei

Die Datei in unserem Beispiel wird im HTML-Format 4.374 Byte groß sein. Der Quelltext enthält neben Eigenwerbung eine gigantische Anzahl von Style Sheets, obwohl es dafür keinerlei Notwendigkeit gibt. Daneben gibt es einige überflüssige HTML-Tags.

Abbildung 7.15:  So sieht die Originaldatei in einem neuen Browser aus

Abgesehen davon, dass die Datei in älteren Browsern Schwierigkeiten machen kann, wird sogar ein Tool mit Kompressionsverfahren an den Style Sheets scheitern, denn diese werden nicht optimiert. Ohne manuelles Eingreifen bekommt das Kompressionstool von 1st Page 2000 die Datei nur auf 4.144 Bytes. Realistisch könnte man die Datei manuell auf vielleicht 800 Byte oder weniger bekommen, indem man die Style Sheets durch HTML-Anweisungen ersetzt und schlechtes HTML optimiert (ohne wesentlichen Verlust der Darstellungsqualität). Aber durch die ausufernde Verwendung von Style Sheets wird auch die manuelle Optimierung von solchen Webseiten ein ungemütliches und aufwändiges Verfahren.

Die Optimierung von Quellcode auf diese Art und Weise macht übrigens bei compilierten Sprachen keinen Sinn. Dort sorgt der Compiler (zumindest bei neueren Techniken) dafür, dass der resultierende Programmcode in dieser Art sowieso optimiert wird. Weder die Länge der Bezeichner noch die reduzierte Verwendung von Syntaxstrukturen hat bei optimierten Compilern einen Effekt auf den endgültigen Programmcode. Da hat Lesbarkeit und Wartbarkeit des Quelltextes Priorität. Zumal dort zudem die Verschleierung von Quelltextinformationen irrelevant wird.

Strukturieren und aufteilen

Ein in Bezug auf Wartbarkeit sehr wichtiges Thema ist die Strukturierung von Inhalten. Auch wenn es am Anfang kaum sinnvoll erscheint, sollte jedes Webprojekt soweit wie möglich strukturiert werden. Das bedeutet, soweit es realisierbar ist, sollten unterscheidbare Elemente einer Webseite auseinander dividiert werden. Also Scripte, Stilvereinbarungen und HTML- Text sollten erst einmal möglichst in getrennte Dateien gegliedert werden.

Dazu sollte für jeden referenzierten Dateityp ein eigenes Verzeichnis angelegt werden. Das bedeutet, ein Verzeichnis für Grafiken (eventuell sogar noch unterteilt in verschiedene Unterverzeichnisse oder parallele Ordner für animierte Grafiken, Buttons usw.), eines für Java-Applets, eines für externe Scripte, eines für externe Stildateien usw. Dazu sollte man auf jeden Fall prägnant gewählte Dateinamen wählen.

Es macht übrigens wenig Sinn, Dateinamen durchzunummerieren. Spätestens, wenn eine Datei gelöscht wird oder in der Logik eine Datei zwischengeschoben werden muss, wird das Konzept hinfällig.

Das Verfahren scheint am Anfang recht aufwändig und überzogen, aber selbst bei kleinen Webprojekten verliert man im Laufe der Zeit schnell den Überblick, wenn man alle Dateien in einem Ordner vorhält. Die Wartbarkeit wird extrem erhöht, wenn man die Aufteilung vornimmt.

Weder Stilvereinbarungen noch Scripte müssen in jeweils einer einzelnen externen Datei notiert werden. Sofern man mit getrennten Verzeichnissen arbeitet und sinnvolle Dateinamen wählt (plus geeigneter Dokumentation), spricht viel dafür, jeweils mehrere Dateien zu nehmen. Sie sollten bedenken, dass auch diese Dateien natürlich über das langsame Netz übertragen werden müssen. Wenn eine HTML-Datei beispielsweise nur eine Funktion aus einer externen JavaScript-Datei benötigt und diese in einer riesigen Datei - möglichst noch am Ende - notiert ist, kann das natürlich auch auf Kosten der Ladezeit gehen. Lieber unterteilt man in verschiedene kleinere Dateien und referenziert bei Bedarf mehrere Dateien in einer Webseite gemeinsam.

Zusammenfassung

Es gibt zwar keine Programmierung, ohne dass Fehler gemacht werden. Es gibt aber zahlreiche Möglichkeiten, diese Fehlerquellen zu reduzieren und - falls doch Fehler auftreten - diese mit sinnvollen Konzepten zu suchen. Die Techniken zum Auffinden und Beseitigen von Fehlern gelten nicht nur in JavaScript, sondern in nahezu jeder Programmier- und Scriptsprache gleich oder zumindest ähnlich. Auch in HTML kann man viele der Überlegungen sinnvoll anwenden. Dies gilt in gleicher Weise für den Vorgang der Optimierung, der bei HTML und Scriptsprachen eine erhebliche Beschleunigung des Ladevorgangs einer Webseite bewirken kann.

Fragen und Antworten

Frage:
Warum ist JavaScript nicht so fehlertolerant wie HTML?

Antwort:
In Scripten bauen Schritte massiv aufeinander auf. Außerdem gibt es gewisse Syntaxstrukturen, die geschützt werden müssen. Wenn vorher ein Problem durchgelassen würde, könnte das ungeahnte Folgen haben. Aber auch so kann ein falsches Script sogar den Browser abschießen.

Frage:
Lässt sich jede Webseite nach der funktionellen Fertigstellung noch optimieren?

Antwort:
Im Prinzip ja, denn meist steht ja bei der Erstellung erst die Funktion im Vordergrund. Erst wenn man das gesamte Werk beurteilen kann, zeigen sich die Stellen, welche sich für eine Optimierung anbieten. Besonders von Tools erstellte Webseiten bieten gigantische Optimierungsmöglichkeiten.

Frage:
Wann sollte man eine Webseite optimieren?

Antwort:
Möglichst erst, wenn die Webseite sonst vollkommen fertig ist. Auch hier gilt, dass erst die Betrachtung der Gesamtseite die richtigen Ansätze offenbart.

Frage:
Sollte man jede Webseite optimieren?

Antwort:
Nein, bei kleinen Seiten mit wenig Text und im Verhältnis vielen Multimedia-Elementen macht der Aufwand kaum Sinn. Die Gefahr, Fehler zu machen, ist auch nicht unerheblich. Eine schnell mal durchgeführte Optimierung führt oft dazu, dass man ein Fass ohne Boden vorfindet.

Workshop

Kontrollfragen

Im Anhang »Antworten zu den Kontrollfragen« finden Sie die Antworten zu den jeweils am Ende einer Lektion notierten Fragen.

  1. Was ist ein typographischer Fehler?
  2. Was stimmt nicht an der Variablendeklaration?
    var 5i;
  3. Was stimmt nicht an der Syntax?
    function test();
    {
    document.write('<HTML>');
    }
  4. Was stimmt nicht an der Syntax?
    var i;j;k;l;
  5. Was stimmt nicht an der Syntax?
    var i,j,k,l
  6. Was stimmt nicht an der Syntax?
    var i j k l;

  7. Was lässt sich an der nachfolgenden Syntax ohne großen Aufwand optimieren?
    function schreibeWebseite()
    {
    document.write('<html>');
    document.write('<head>');
    document.write('</head>');
    document.write('<body link="#9F9F9F" bgcolor="#FFFFFF">');
    document.write('</body>');
    document.write('</html>');
    }


vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbackKapitelanfangnächstes Kapitel


12345

© Markt+Technik Verlag, ein Imprint der Pearson Education Deutschland GmbH