vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbacknächstes Kapitel


Tag 6

Einführung in dynamische Webanwendungen und Datenbankentwicklung

Was sind eigentlich datenbankgestützte Websites? Welche Vorteile bieten sie gegenüber »normalen« Websites? Welche Kenntnisse braucht man, um sie zu erstellen? Das sind die Fragen, auf die wir in der heutigen Lektion eine Antwort finden wollen. Heute können wir uns einmal zurücklehnen und den Computer ausgeschaltet lassen. Sie werden lernen, was dynamische Websites sind und welche Konzepte dahinter stehen. Leider geht das nicht ohne etwas Theorie. Die heutigen Themen im Überblick:

6.1 Dynamische Websites

An den vorausgegangenen Tagen haben wir uns mit der Erzeugung von statischen Websites befasst und haben gerade einmal das erste Viertel des Buches hinter uns gebracht. Zu was in aller Welt muss man nun noch so viel Papier und Druckerschwärze verbrauchen? Nun, für die Erklärung, wie man dynamische Websites erstellt. Aber was versteht man eigentlich darunter?

Wenn eine Website dynamisch ist, so heißt das, dass Inhalte eines HTML-Dokuments nicht - wie wir das bisher von HTML-Dateien kennen - statisch, also unveränderlich, sind, sondern ausgetauscht werden können. Diese neuen Inhalte werden dynamisch in Abhängigkeit von den Eingaben des Anwenders erzeugt. Nun haben wir ja schon Seiten erstellt, bei denen sich Objekte verändert oder bewegt haben, wenn der Anwender z.B. den Mauszeiger darauf gesetzt hat. Sind das also auch schon dynamische Websites? Nein, eigentlich nicht. Der Code, auf dem diese Effekte basieren, ist bereits in das HTML- Dokument integriert, alle erforderlichen Rechenoperationen werden clientseitig, vom System des Anwenders, durchgeführt.

Bei echten dynamischen Sites wird ein HTML-Dokument aus Programmcode generiert, der vom Server abgearbeitet wird. Rufen zwei Besucher einer Site dasselbe Dokument ab, kann sich der HTML-Code dieser Dateien durchaus unterscheiden. Zur Erstellung einer individualisierten HTML-Seite wird also auf die Rechenleistung des Servers zugegriffen, der das Dokument auf der Grundlage der Anwendereingaben erzeugt. Diese Seite kann nun die Art von dynamischen Elementen enthalten, die wir in den vorhergehenden Lektionen kennen gelernt haben, oder ein gewöhnliches statisches HTML-Dokument sein. Der entscheidende Punkt ist, dass die Seite während der Laufzeit vom Server erzeugt und dann an den Client übertragen wurde. Hinter dynamischen Websites steht gewöhnlich ein Datenbanksystem, um die Datenbestände möglichst effektiv zu speichern und zu verwalten. Dynamisch erzeugte Dokumente lassen sich manchmal an der Extension der angeforderten Datei wie .cgi, .php oder .jsp - kurz allem, was von .htm oder .html abweicht - erkennen.

Die Extension einer Datei ist zwar noch keine hundertprozentige Garantie, dass hinter der Website eine Datenbank steht, aber doch ein ziemlich verlässlicher Hinweis. Sie ist auch ein Hinweis darauf, welche Technologie verwendet wird, um die Site dynamisch zu machen. Es gibt zwei verbreitete Ansätze, um dynamische Websites zu erzeugen: den Einsatz von CGI-Scripts und die Verwendung eingebetteter Skriptsprachen.

Traditionelle Programmierung von Web-Applikationen

Traditionell konzentrierte man sich bei der Programmierung von Web-Applikationen darauf, spezialisierte Anwendungen zu schreiben, die genau definierte Aufgaben erledigen, die so genannten CGI-Scripts (CGI: Common Gateway Interface). CGI-Scripts sind Anwendungen, die sich im Prinzip nicht von den Programmen unterscheiden, die Sie lokal auf Ihrem Rechner einsetzen, nur dass sie auf einem Server installiert sind. Es sind Programme wie andere auch, nur verwenden sie ein HTML-Interface.

Das Hauptproblem von CGI-Scripts ist, dass sie eine Menge Speicherplatz auf dem Server beanspruchen. Eine typische Perl-Anwendung (Perl ist die am weitesten verbreitete Programmiersprache für CGI-Scripts) belegt ungefähr 5 MB RAM. Für einen modernen UNIX- oder NT-Server ist das noch kein Problem, wohl aber das ständige Laden des Programms in den Arbeitsspeicher und das anschließende Löschen. Diese ständigen Lade- und Löschvorgänge machen CGI-Applikationen weit ressourcenhungriger als eingebettete Scriptsprachen, auf die wir im Anschluss eingehen.

Bevor sich jetzt allgemein Unmut breit macht, möchte ich darauf hinweisen, dass man das Perl-Problem elegant umgehen kann. Mit der mod_perl-Library für den Apache-Webserver bzw. dem Perl-Add-on von ActiveState für den IIS kann man einen Perlinterpreter in den Webserver integrieren. So muss nicht jedes Mal ein eigener Perl-Prozess gestartet werden, wenn ein CGI-Script aufgerufen wird.

CGI-Scripts werden normalerweise programmiert, um eine genau definierte Aufgabe auszuführen. Auf meiner Website unter http://jray.ag.ohio-state.edu/ finden Sie verschiedene solcher CGI-Scripts. Es handelt sich nicht um die üblichen seitenlangen Webapplikationen, sondern sie sind für einen speziellen Einsatzzweck geschrieben (Besucherstatistiken, grafische Netzwerkanalyse usw.).

Der »Pferdefuß« an den herkömmlichen CGI-Programmiersprachen ist, dass sie nicht für die Programmierung von Webapplikationen konzipiert wurden. Wofür Sie bei einer herkömmlichen CGI-Applikation mehrere Dutzend Zeilen Code brauchen, lässt sich mit eingebetteten Scriptsprachen vielleicht mit einer einzigen Zeile erledigen. Wenn Sie Erfahrung mit CGI-Scripts haben, werden Sie feststellen, dass der Einsatz von eingebetteten Sprachen den Sourcecode drastisch verkürzen kann.

In den HTML-Code eingebettete Scriptsprachen

Eingebettete Scriptsprachen sind die Nachfolger der CGI-Sprachen. In puncto Benutzerfreundlichkeit und Leistungsumfang übertreffen sie herkömmliche CGI-Scripts bei weitem. Der Hauptunterschied zwischen CGI-Scripts und eingebetteten Scriptsprachen lässt sich am besten an der Frage festmachen, wer sozusagen die »Oberhoheit« über den Code hat. Bei CGI-Scripts steht der Code unter der Regie der Programmiersprache, die das HTML-Dokument erzeugt. Bei eingebetteten Sprachen steuert das HTML-Dokument den Code. Statt also erst ein Programm zu schreiben, das dann anschließend eine HTML-Datei ausgibt, schreiben Sie gleich den erforderlichen HTML-Code und setzen dort, wo Elemente dynamisch verändert werden sollen, den entsprechenden Anwendungscode ein.

Auch hinsichtlich der Abarbeitung unterscheiden sich die Programmiersprachen. Eingebettete Sprachen werden vom Server abgearbeitet, wenn er die Seite an den Client schickt. Hierzu muss kein externes Programm aufgerufen werden. Der Interpreter für die Sprache ist in den Server selbst eingebunden. Das macht eingebettete Sprachen höchst effektiv, was Geschwindigkeit und Ressourcenbedarf angeht.

Ein anderer fantastischer Vorteil von eingebetteten Sprachen ist, dass man mit ihnen direkt auf Datenbanken zugreifen kann. Datenbankunterstützung wurden bei den meisten Programmiersprachen erst nachträglich integriert. Die Entwickler eingebetteter Sprachen erkannten jedoch frühzeitig das Potenzial, das im direkten Zugriff auf Datenbanken aus dem HTML-Code heraus liegt und integrierten dieses Feature von vorneherein in diese Sprachen. Geschwindigkeit und leichte Anwendbarkeit sind nur zwei der Vorteile dieser optimal aufeinander abgestimmten Technologien.

Die Kombination von eingebetteten Scriptsprachen und HTML-Code bietet also große Vorteile. In den letzten zwei Jahren sind eingebettete Sprachen daher zu einem wahren Siegeszug angetreten und werden mittlerweile auf breiter Front eingesetzt. UltraDev unterstützt drei Typen eingebetteter Scriptsprachen und ist somit flexibel einsetzbar. Außerdem erlaubt das Programm als eines der ersten dieser Art eine Live-Vorschau dynamischer Websites.

6.2 Dynamische Sites verstehen

Auch wenn es vielleicht den Anschein hat, dass sich die Entwicklung einer dynamischen Website bis auf den Punkt, dass sie eine HTML-Oberfläche benötigt, in nichts von der Programmierung einer anderen Anwendung unterscheidet, so ist hierbei doch eine völlig andere Vorgehensweise vonnöten. Was den Entwicklern von Web-Applikationen das Leben etwas vergällt, ist das HTTP-Protokoll. Was geschieht zum Beispiel, wenn Sie eine Anwendereingabe entgegennehmen, sie verarbeiten, eine weitere Information abfragen, sie verarbeiten und dann das Ergebnis ausgeben? Mit einer gewöhnlichen Programmiersprache ist das kein Problem. Sie strukturieren den Programmablauf genau in der Reihenfolge, wie die einzelnen Bearbeitungsschritte ausgeführt werden sollen.

Soll eine Anwendung im Web laufen, müssen Sie an die Programmierung anders herangehen. Der Grund liegt darin, dass immer nur ein Programmschritt auf einmal implementiert werden kann und dass diese Programmschritte irgendwie miteinander verknüpft werden müssen. Nun ist aber das HTTP-Protokoll ein verbindungsloses Protokoll, und zwischen Client und Server besteht zwischen dem Aufruf von zwei dynamisch erzeugten Seiten keine Verbindung. Jede einzelne Seite, die ausgegeben wird, ist - sofern sie dynamisch erzeugt wurde - das Ergebnis der individuellen Ausführung eines Programms auf dem Server.

Wenn der Anwender ein Formular abschickt, geht es an den Server, wird dort abgearbeitet und an den Anwender wird eine Ergebnisseite übermittelt. Nach der Übertragung sind die Daten auf dem Server nicht mehr existent und die Verbindung zwischen Client und Server wurde gelöscht. Also, was tun, wenn Sie diese Daten eigentlich für weitere Operationen benötigen?

Um eine konstante Verbindung zwischen Client und Server über mehrere Anwenderzugriffe hinweg aufrecht zu erhalten, müssen Sie die Eigenheiten des HTTP- Protokolls überlisten und mit einem so genannten Session-Management arbeiten. Einfach ausgedrückt ist das Session-Management ein Trick, um zwischen dem Anwender und dem Webserver eine permanente virtuelle Verbindung einzurichten, während in Wirklichkeit keine dauerhafte Verbindung besteht. Für die Realisierung eines Session-Managements können Sie zwischen zwei Möglichkeiten wählen - dem Einsatz von Cookies und der Übergabe von Variablen.

Variablenübergabe

Variablenübergabe ist eine Möglichkeit, die Werte von verschiedenen Variablen von einem HTML-Dokument an das nächste weiterzugeben. Sie kennen sicher URLs wie die folgende, die sich nicht auf eine bestimmte statische HTML-Seite beziehen:

http://www.someplaceurl.com/test.jsp?firstname=John&lastname=Ray

In diesem Beispiel werden die Variablen firstname und lastname an das Programm test.jsp auf dem Server mit den Werten John bzw. Ray übertragen. Sollen bei einer Anwendung Daten zwischen Seiten übergeben werden, kann man diese Werte in Variablen ablegen und an den Link anhängen, der diese Seite aufruft. Wird der Link aktiviert, werden die Daten »weitergereicht«. Man bezeichnet diese Art der Variablenübergabe als GET-Methode. Sie wird häufig verwendet, doch erzeugt sie hässliche Monster-URLs, die zudem manchmal unerwünschte Einblicke ins Innenleben einer Website zulassen. Ein weiterer Nachteil ist, dass beim Bookmarken von Seiten, die mit der GET-Methode erzeugt wurden, diese Variablen mit abgelegt werden. Werden diese Seiten nun wieder aufgerufen, werden auch die Variablen wieder mitgesendet, die beim ersten Aufruf der Seite vom Webserver erzeugt wurden. Der Vorteil der Variablenübergabe per GET-Methode ist, dass man die erforderlichen Links gut von Hand erzeugen kann. Parameter aus Datenbankabfragen oder an anderer Stelle eingegebene Benutzerdaten lassen sich so problemlos in einen Link schreiben.

Es folgt ein Codebeispiel für einen Request an den Webserver unter Verwendung der GET-Methode:

GET /thetest.jsp?firstname=John&password=notonyourlife&lastname=Ray&action=transferbankfunds HTTP/1.0
Host: poisontooth.com:
User-Agent: Johnclient.pl (Linux)

Daten lassen sich alternativ auch per POST-Methode übergeben. Sie wird gewöhnlich dann verwendet, wenn man Formulardaten an den Server übermitteln möchte, ohne dabei sämtliche Daten in die URL einbetten zu müssen. Gerade bei sehr umfangreichen Formularen ist es nicht wünschenswert, Daten per URL zu übergeben. Die POST- Methode sendet Daten als Teil der Request-Mitteilung an den Server.

POST /thetest.jsp HTTP/1.0
Host: poisontooth.com:
User-Agent: Johnclient.pl (Linux)
Content-type: application/x-www-form-urlencoded
Content-Length: 75
firstname=John&password=notonyourlife&lastname=Ray&action=transferbankfunds

Wie Sie sehen, sind die Unterschiede zwar klein, aber umso weitreichender. Abgesehen davon, dass der resultierende HTML-Code übersichtlicher ist, können auch größere Datenmengen per Formular an das Programm übergeben werden.

Mit dem POST-Befehl können Sie jedoch nur dann Daten per HTML übergeben, wenn Sie Formulare benützen. Sie können nicht selber eine URL erzeugen und damit per POST-Befehl Daten übergeben. Dadurch lässt sich die POST-Methode nur begrenzt einsetzen. Verwenden Sie jedoch eine Reihe von Formularen, die der Anwender ausfüllen soll, ist die POST-Methode sehr nützlich.

Sitzungsvariablen

Egal für welche Art der Variblenübergabe Sie sich letztlich entscheiden, das Problem, wie Sie Ihre Daten verwalten, ist damit noch nicht gelöst. Wenn Sie z.B. eine Warenkorb- Funktion programmieren wollen, die alle gekauften Waren in einer Einkaufsliste speichert, wäre es nicht gerade effizient, eine Warenkorb-Variable zu definieren, an diese Variable dann alle Bestellnummern zu hängen und dann per URL an die nächste Seite zu übergeben. Zur Übergabe dieser Informationen empfiehlt sich die Verwendung von Sitzungsvariablen.

Sitzungsvariablen sind virtuelle Variablen, die für die Dauer einer Anwendungssitzung vergeben werden. In Sitzungsvariablen lassen sich beliebige Werte ablegen, die nur für die jeweilige Sitzung gültig sind. Da sich die Dauer einer Anwendersitzung nicht vorhersagen lässt, werden die Variablen gelöscht, sobald der Anwender die Seite wieder verlässt. Manchmal werden Sitzungsvariablen auch zeitabhängig gelöscht. Der Anwender wird dann automatisch vom System ausgeloggt, und die gespeicherten Informationen werden gelöscht. Haben Sie nicht auch schon mal einen Webshop besucht und ein paar Dinge in Ihren Einkaufskorb gelegt, um sie dann schließlich doch nicht zu kaufen? Wahrscheinlich haben Sie dann Ihren Einkaufswagen nicht geleert, sondern einfach das Browserfenster geschlossen. Falls Sie dann am nächsten Tag nochmal auf die Site gegangen sind, war Ihr Einkaufskorb wahrscheinlich leer, d.h., die Sitzungsvariable wurde gelöscht.

Sitzungsvariablen können, wenn sie intelligent eingesetzt werden, sowohl dem Anwender als auch dem Programmierer das Leben leichter machen. Man kann damit sowohl komplexere als auch sicherere Anwendungen schreiben, als das unter der Verwendung der üblichen Art der Variablenübergabe möglich wäre. Werden Anwendungen mit Sitzungsvariablen aber nicht sauber programmiert, kann sich der Effekt ins Gegenteil verkehren. Bei den meisten Programmiersprachen, die die Definition von Sitzungsvariablen gestatten, können Sie die vollständige Warenkorbstruktur in einer einzigen Variablen abbilden. Das ist zwar möglich, kann aber den Server schon mal in die Knie zwingen. Komplexe Strukturen, die in einer einzigen Variablen abgelegt werden, müssen zuerst serialisiert, d.h. in eine Datenfolge umgewandelt werden, die auf dem Server gespeichert werden kann. Wird die Information nun aus irgendeinem Grund noch einmal abgerufen, muss sie wieder zurückkonvertiert werden. Laufen mehrere solcher Prozesse simultan ab, kann ein Server in puncto Rechenzeit und Ressourcen schon mal an seine Grenzen kommen.

Es empfiehlt sich daher, Datenbanken so zu modellieren, dass sie die Struktur der Daten logisch abbilden, und für den Zugriff auf die einzelnen Datensätze jeweils eigene Sitzungsvariablen zu definieren. Der Webserver kann dann sämtliche Daten an den Datenbankserver weitergeben und wird dadurch entlastet.

Ein weiterer Variblentyp, der bei dynamischen Anwendungen zum Einsatz kommt, ist die so genannte Applikationsvariable. Dieser Typ von Variable wird für sämtliche Anwendersitzungen definiert und kann von der gesamten Webanwendung jederzeit abgerufen werden.

Ähnlich globalen Variablen gelten Applikationsvariablen als wenig sinnvolles Konzept. Zur Erstellung interner Statistiken von Webanwendungen können sie jedoch recht nützlich sein.

Über Session-IDs lassen sich Anwendersitzungen eindeutig identifizieren. Sie sind eine »Gedächtnisbrücke« für den Server, die ihm hilft, sich an bestimmte Werte wieder zu »erinnern«, die der Anwender während einer Session bereits eingegeben hat. Für den Programmierer heißt das, dass er lediglich eine ID von einer Seite zur nächsten übergeben muss, mehr nicht. Leider gibt's auch hier ein kleines Problem mit der Bookmark-Funktion des Browsers. Wird eine URL mit einer Session-ID in der URL als Lesezeichen abgespeichert, kann es - je nachdem, wie die Anwendung konfiguriert ist - zu Fehlermeldungen wie »session expired« oder nicht vorhersehbaren Fehlfunktionen kommen, wenn die Seite wieder aufgerufen wird.

Die perfekte Lösung wäre, wenn man das Session-Management so handhaben könnte, dass man Variablen ohne spezielle Programmierung weitergeben kann und die Vorgänge für Anwender und Programmierer transparent sind. Und diese Möglichkeit gibt es: Cookies.

Cookies

Cookies sind eine Möglichkeit, wie eine Webanwendung auf dem Clientrechner Informationen ablegen und wieder auslesen kann. Bei vielen Anwendern läuten beim Thema Cookies allerdings die Alarmglocken. Wenn Cookies auf meinem Rechner Daten ablegen können, wer garantiert mir dann, dass sie nicht irgendwelche unerwünschten Transaktionen vornehmen und Daten auf meinem Rechner zerstören? Nun, das ist schon der schlichten Dateigröße wegen nicht möglich. Cookies können gerade mal einige Tausend Bytes haben - was kaum ausreicht, um eine größere Menge an sinnvollen Informationen zu speichern, geschweige denn ganze Programme. Zudem werden Cookies in einer eigenen Datei gespeichert. Sie können diese Datei jederzeit öffnen und ihre Inhalte überschreiben oder löschen.

Als Netscape-Anwender können Sie nach der Datei cookies.txt suchen, verwenden Sie den Internet Explorer, sehen Sie im Ordner Cookies im Windowsverzeichnis nach. Nachfolgend ein Ausschnitt aus meiner eigenen Cookie-Datei:

#Netscape HTTP Cookie File
#http://www.netscape.com/newsref/std/cookie_spec.html
#This is a generated file!Do not edit.

free.aol.com FALSE /tryaolfree FALSE 993674880 user 31031923
.excite.com TRUE / FALSE 1057815167 mesp_popup y2k%fDyes
.excite.com TRUE / FALSE 1057815167 UID 9A7BF6F2Df023B94
.excite.com TRUE / FALSE 1057815167 registered no
.doubleclick.net TRUE / FALSE 1920499223 id 8bccs8ce
.deja.com TRUE / FALSE 1102550463 GTUID 04.48861.3.0.f.4363

Jede kommerzielle Website verwendet aus dem einen oder anderen Grund Cookies. Meine Cookie-Datei zählt momentan gut 400 Cookies, obwohl ich meistens technikorientierte Sites ansurfe und nichts online einkaufe.

Ein weiterer Vorbehalt gegen Cookies ist, dass man mit ihrer Hilfe das Surfverhalten von Anwendern über mehrere Websites hinweg verfolgen kann. Für manche Sites ist das zwar richtig, aber nur, weil diese Sites untereinander kooperieren. Cookies sind so konzipiert, dass die darin gespeicherte Information nur von der Site ausgelesen werden kann, die das Cookie gesetzt hat. Damit soll Datenklau seitens anderer Webanwendungen verhindert werden. Für die einzelne Site ist es jedoch sehr wohl möglich, die Aktionen des Anwenders zu rekonstruieren. Und das ist ja genau das, was wir erreichen wollen: bestimmte Vorgänge auf der Website einem einzelnen Anwender zuordnen.

Mithilfe von Cookies kann der Programmierer ohne besonderen Programmieraufwand Variablen setzen, auf die von jeder Seite der Website aus zugegriffen werden kann. Cookies werden mit einer Pfadangabe gesetzt. Seiten, die innerhalb dieses Pfades stehen, haben Zugriff auf das Cookie. Den folgenden Code schickt eine Website an den Browser mit der Anfrage, ob ein Cookie gesetzt werden darf:

Set-Cookie: SESSION=3424; path=/shopping

Sobald das Cookie gesetzt ist, wird jedes Mal, wenn der Client eine URL anfordert, die innerhalb des Verzeichnisses »Shopping« steht, an den Server folgende Mitteilung geschickt:

Cookie: SESSION=3424

Mit der Anweisung path=/ definiert die Webanwendung, wann und von welchen Seiten aus der Client die Cookie-Information an die Webanwendung zurückschickt.

Wie sieht nun der typische Einsatz von Cookies in Webanwendungen aus? Sind sie ein »Speichermedium«, das sämtliche Informationen aufnimmt, die zwischen den einzelnen Seiten einer Webanwendung übergeben werden müssen? Das wird wohl nur in den seltensten Fällen so sein, wenn die Informationsmenge so gering ist, dass man diese Daten am besten direkt in ein Cookie schreibt. Arbeiten Webanwendungen mit Sitzungsvariablen, dienen Cookies gewöhnlich der Speicherung der vergebenen Session- IDs.

Eine Frage wird zwangsläufig immer wieder gestellt: »Soll ich auf meiner Website mit Cookies arbeiten?« Ich persönlich halte Cookies für eine wunderbare Sache, um mit dem geringsten Programmieraufwand dem Besucher ein Höchstmaß an Anwendungsfreundlichkeit zu bieten. Wenn Sie Ihre Besucher darüber aufklären, warum und wie Sie Cookies einsetzen, dürfen Sie auch mit entsprechender Akzeptanz rechnen. Die Alternative zu Cookies wäre, mit Variablenübergabe zu arbeiten, eine in meinen Augen alles andere als verlockende Perspektive. Bei den verschiedenen Webanwendungen, die wir im Laufe dieses Buches noch gemeinsam entwickeln werden, werden wir jeweils die Techniken verwenden, die für den jeweiligen Zweck am sinnvollsten sind.

Mit UltraDev können Sie beide Varianten des Session-Managements automatisieren. Das Programm erlaubt sowohl die Verwendung von Cookies als Art globaler Variable als auch die Übergabe von Variablen an die nächste Seite per Link.

6.3 Dynamische Websites kreieren

Die Entscheidung, ob und wann man eine Website um dynamische Funktionen erweitert, sollte nicht überstürzt getroffen werden. Ich habe Websites betreut, die aus den unterschiedlichsten Gründen als statische Websites konzipiert und umgesetzt wurden. Die monatliche Aktualisierung dieser Sites erfordert nun aber jedes Mal mehrere Arbeitsstunden, um alle betroffenen Seiten auf den neuesten Stand zu bringen. Je umfangreicher solche Sites mit der Zeit werden, desto aufwändiger wird es, sie zu warten, und umso größer werden die Schwierigkeiten, sie dynamisch an eine Datenbank anzubinden. Es empfiehlt sich dringend, für jede Website, die aus mehr als einem HTML- Dokument besteht, eine Sitemap anzulegen, auch wenn dies am Anfang völlig überflüssig erscheint. Eines vielleicht gar nicht so fernen Tages werden Sie ganz froh darüber sein.

Verschiedene Typen dynamischer Websites

Wenn abzusehen ist, dass eine Website häufig aktualisiert werden muss, ist sie ein »Bilderbuchkandidat« für eine Datenbankanbindung. Dynamische Websites entlasten den Bearbeiter von der lästigen Pflicht, jedes Mal den gesamten HTML-Code aktualisieren zu müssen, wenn sich ein Inhalt ändert. Sie müssen nur einmal eine Dateneingabemaske erstellen, mit der sich dann ebenso leicht arbeiten lässt wie mit einer gewohnten Office- Anwendung.

Auch Sites, bei denen größere Mengen an Benutzerdaten anfallen, eignen sich gut zur Dynamisierung. Erstaunlich oft werden die Ergebnisse von Anwenderbefragungen und Kundenkommentare einfach als E-Mails zusammengefasst und an den Betreiber der Site weitergeleitet. Einige Hundert CGI-Applikationen sind in der Folge damit beschäftigt, diese per Formular gewonnenen Daten in lesbaren Text umzuwandeln und dann per E-Mail an ein Wesen aus Fleisch und Blut zur endgültigen Bearbeitung weiterzuleiten. Da ist es dann interessant zu hören, dass es eigens Programme gibt, die solche per Webanwendung generierten E-Mails zur leichteren Bearbeitung auf Empfängerseite aufbereiten und in Datenbanken speichern. Wäre es da nicht viel einfacher, diese Daten nicht gleich von Anfang an in einer Datenbank zu erfassen, anstatt den Umweg über Formular zu E-Mail und von E-Mail zu Datenbank zu gehen?

Ähnlich verhielt es sich bei einigen großen kommerziellen Sites, an deren Redesign ich mitgearbeitet habe. Anfragen zu Produkten oder andere Daten, die ein Anwender in ein Formular auf der Website eingeben hatte, wurden per E-Mail an den Betreiber der Site weitergeleitet. Dort wurden die E-Mails vom Systemadministrator ausgedruckt und an die verschiedenen Kundenbetreuer zur endgültigen Bearbeitung weitergeleitet. Das ist eigentlich nicht die Art von Prozedere, an die man beim Wort E-Commerce denkt. Hier zeigte sich einmal mehr, wie schwierig es ist, bestimmte Praktiken wieder auszumerzen, wenn sie sich erst einmal eingeschliffen haben.

Und schließlich eignen sich alle Websites zur Umstellung auf Datenbanken, die große Mengen von Information hosten (und die für den Anwender gut navigierbar gemacht werden sollen). Hat der Anwender z.B. die Möglichkeit, ganze Bücher zu durchsuchen und sich die Ergebnisse strukturiert anzeigen zu lassen, so ist dies für den Nutzwert natürlich unvergleichlich höher, als nur den reinen Text zur Verfügung zu stellen oder allgemeine Informationen über das Buch. Kann der Anwender seine Suchabfragen selbst definieren, wird eine Webdatenbank zu einem fantastischen Recherchewerkzeug.

Die Planung von dynamischen Websites

Der erste Schritt zur Umsetzung einer dynamischen Website besteht in der gründlichen Planung. Wenn Sie schon im Vorfeld die richtigen Entscheidungen treffen, kann Ihnen das später so manches graue Haar ersparen - es ist nämlich alles andere als leicht, eine bis dato statische Website datenbankgerecht aufzubereiten. Tatsächlich können Sie sich gar nichts Schlimmeres antun, als eine Website zunächst statisch anzulegen und sich dann im Nachhinein doch dafür zu entscheiden, die Site an eine Datenbank anzubinden. Je umfangreicher und vielschichtiger eine Site wird, desto stärker sind HTML-Code und Inhalt ineinander verzahnt. In solchen Fällen lässt sich der Übergang von der statischen Website zur dynamischen Webanwendung meistens nur durch völlige Neugestaltung bewältigen. Nachfolgend wird auf die einzelnen Planungsschritte eingegangen.

Eine Sitemap anlegen

Erstellen Sie eine detaillierte Sitemap der Website mit allen Bereichen und einer kurzen Beschreibung der Inhalte, die unter diesen Bereichen liegen. Die Sitemap ist das A und O bei der Planung und Umsetzung einer jeden Website, und für dynamische Websites gilt das noch in weit höherem Maße. Wenn Sie sämtliche Seiten und ihre wechselseitigen Bezüge in einem klaren Struktogramm erfassen, können Sie damit auch gut die Beziehungen erkennen, die zwischen den Daten dieser Seiten bestehen.

Mehrfach vorhandene Informationen ermitteln

Stellen Sie fest, ob und welche Informationen in den jeweiligen Bereichen mehrfach vorhanden sind. Häufen sich solche Elemente oder sind sie sehr umfangreich, kann man sie in einer Datenbank ablegen. Bei der Identifizierung solcher Elemente sollten Sie natürlich den gesunden Menschenverstand walten lassen. Nur weil das Wörtchen »der« 19 Mal auf einer Seite vorkommt, sollten Sie es nicht bei jedem Auftreten aus der Datenbank abrufen. Adressen, Kontaktinformationen, Telefonnummern u.ä. - das sind unsere Kandidaten, die sich zur Aufnahme in die Datenbank empfehlen.

Auf Listen überprüfen

Überprüfen Sie, ob es irgendwelche Listen mit Informationen gibt, die mehr als einige wenige Einträge umfassen. Listen sind eigentlich schon eine Art Datenbank, nur sind sie nicht in elektronischer Form gespeichert. Auf jeder Website gibt es z.B. Linklisten oder Listen von Presseberichten. Diese Listen werden meistens von Mitarbeitern der Firma gepflegt und nicht von der betreuenden Internetagentur. In den Firmen, mit denen ich zu tun hatte, erledigten das die PR- bzw. die Personalabteilung, die die neuen Daten dann an die Agentur weitergaben. Je länger die Liste war, desto häufiger waren auch doppelte Einträge.

Häufige Änderungen lokalisieren

Finden Sie heraus, ob es auf den verschiedenen Seiten Elemente gibt, die häufig verändert oder aktualisiert werden müssen. Der »Lesetipp der Woche« oder ähnliche kurzfristig wechselnde Aufmacher lassen sich gut über eine Datenbank generieren. Ist die Werbeaktion abgelaufen, kann das Buch - um bei diesem Beispiel zu bleiben - in den Archivbereich der Site verschoben werden, sodass sich Interessenten auch später noch über diesen Titel informieren können.

Das Wichtigste bei der Planung datenbankgestützter Websites ist der Grundsatz der Verhältnismäßigkeit. Es gibt keine unfehlbaren Gesetze, wann und unter welchen Umständen eine Website an eine Datenbank angebunden werden sollte oder nicht. Besteht Ihre Site nur aus zwei oder drei HTML-Dokumenten, lohnt es den Aufwand nicht, einen Datenbank- bzw. Anwendungsserver aufzusetzen, um sie ins Netz zu stellen. Bei so kleinen Sites ist manuelle Datenpflege das Mittel der Wahl.

Als professioneller Webdesigner werden Sie allerdings von Kundenseite oft mit der Forderung konfrontiert, dass mit der erstellten Website kein hoher Wartungsaufwand verbunden sein soll. Selbst in diesen Zeiten des Internetbooms möchten die Leute möglichst wenig mit HTML und allem, was damit zusammenhängt, zu tun haben. Die Einrichtung eines Datenbank-Backends ist in solchen Fällen die einfachste Lösung, die Informationen auf der Site von einer Anwendung aus zu verwalten. Der Kunde kann somit seine Website stets auf dem neuesten Stand halten, ohne an irgendeinem Punkt mit dem Code in Berührung zu kommen.

Und schließlich gibt es noch die Leute, die einfach jeder Mode hinterher rennen. Und bei Websites geht der Trend augenblicklich weg von statischen und hin zu dynamischen, datenbankgestützten Anwendungen. In dieser Hinsicht habe ich durchaus schon einige unangenehme Erfahrungen gemacht. Manche Leute wollen einfach nicht einsehen, dass es Fälle gibt, in denen die damit verbundenen Nachteile in keinem Verhältnis zu den wenigen Vorteilen stehen. Statt einfach, um ein Beispiel zu nennen, ein paar Zeilen im HTML-Code anzupassen, muss man nun erst einmal die Datenbank nach dem zugehörigen Datensatz durchsuchen und ihn dann dort ändern. Datenbankgestützte Websites sind in manchen Fällen auch deshalb schwerer zu warten, weil sie, einmal abgesehen von zusätzlich erforderlichen Arbeitsschritten, auch höhere Anforderungen an das Know-how des Bearbeiters stellen. Mit einem UNIX-Zugang und einem einfachen Palm Pilot könnte ich mich auf nahezu jedem Server einloggen und Änderungen an einer Website durchführen. Liegen die Daten in einer Datenbank, dann geht das nicht mehr so leicht.

Treffen Sie diesbezügliche Entscheidungen nur nach reiflicher Überlegung. Setzen Sie nicht irgendwelche Technologien ein, nur weil Ihnen jemand weismachen will, Sie müssten das tun. Vielleicht realisieren Sie eine statische Website und stellen später fest, dass Sie besser doch eine datenbankgestützte Anwendung erstellt hätten. Doch kann es Ihnen genauso gut passieren, dass Sie eine dynamische Website erstellen, die sich als statische Website besser und einfacher hätte pflegen lassen. Die Kunst besteht darin, den später möglicherweise entstehenden Schaden möglichst gering zu halten.

6.4 Datenbankentwurf

Doch bevor wir überhaupt eine datenbankgestützte Website ins Netz stellen können, brauchen wir erst einmal ein Datenbank-Backend, aus dem wir unsere Daten holen können. UltraDev liefert kein solches Backend und sucht auch keines für uns aus. Bevor wir also mit UltraDev dynamische Websites entwickeln können, müssen wir auf unserem Rechner zuerst einen Datenbankserver oder zumindest eine Datenbank wie z.B. MS Access installieren. Aber keine Bange, Sie erhalten später eine schrittweise Anleitung, wie Sie eine MySQL-Datenbank einrichten. Diese Datenbank ist für UNIX-Systeme als Freeware und für Windows NT-Rechner als Shareware erhältlich. Somit kann sie auf jeder beliebigen Plattform, eingeschlossen Mac OS X, eingesetzt werden, und das in vielen Fällen unentgeltlich.

Bevor Sie eine Datenbank anlegen, sollten Sie über die Grundlagen des Datenbankenentwurfs Bescheid wissen. Leider ist es nicht damit getan, dass Sie ein paar Werte in eine Tabelle schreiben und das Ganze dann unter dem Namen Datenbank speichern. Zuerst müssen Sie sich eine Strategie überlegen, wie Sie Ihre Daten sinnvoll strukturieren, damit Sie mit der gespeicherten Information effektiv arbeiten können.

Lassen Sie uns daher anhand eines Beispiels den Aufbau einer sauberen Datenstruktur nachvollziehen.

Terminologie der Datenmodellierung

Wenn Sie eine Datenbank anlegen, sollten Sie auch die damit verbundene Terminologie kennen. Beginnen wir mit dem Wichtigsten: Was versteht man unter Normalisierung?

Normalisierung

Unter Normalisierung versteht man den Prozess, eine Menge von Daten so weit zu reduzieren, dass sämtliche Redundanzen, also mehrfach vorhandene identische Datensätze, ausgeschlossen sind. Hierarchische Datenbanksysteme speichern mehr Daten, als tatsächlich erforderlich sind. Durch Normalisieren wird diese monolithische Datenstruktur heruntergebrochen in mehrere kleinere, besser handhabbare »Datenpakete«. Ziel der Normalisierung ist es, Redundanzen auszuschließen und die Aktualisierung des Datenbestands zu vereinfachen.

Der Prozess der Normalisierung erfolgt in mehreren Schritten, wie wir heute noch sehen werden. Diese Schritte kann man als Etappen sehen, um die eine Datenmenge Zug um Zug der endgültigen Form zugeführt wird, die sie dann in der Datenbank haben wird.

Entitäten

Entitäten sind so etwas wie ein Oberbegriff, unter dem wir spezielle Daten speichern. Praktisch sind sie gleichbedeutend mit den Tabellen in einer Datenbank. Tatsächlich benennt man die Tabellen einer Datenbank nach diesen aufgestellten Entitäten.

Attribute

Entitäten setzen sich aus Attributen zusammen. In gewöhnliche Datenbanksprache übersetzt heißt das, dass Tabellen Felder enthalten. Ein Attribut ist ein Feld innerhalb einer Entität. Sie heißen Attribute, weil sie die Entität näher beschreiben. Die Entität Auto könnte z.B. die Attribute Jahr oder Farbe besitzen.

Identifikationsschlüssel

Unter Identifikationsschlüssel versteht man ein Attribut oder eine Gruppe von Attributen, über die ein bestimmter Datensatz und nur dieser Datensatz eindeutig identifiziert werden kann. Für die Definition eines Identifikationsschlüssels gelten drei feste Vorschriften:

Beziehungen

Beziehungen sind genau das, was sich im Namen ausdrückt - die Art und Weise der Verbindung, die zwischen zwei Informationen oder Datensätzen besteht. Folgende drei Arten oder Grade der Beziehung sind zwischen Entitäten möglich:

Beispiel für eine Normalisierung

Nehmen wir an, Sie möchten eine Datenbank für eine Schule erstellen, die die folgenden Informationen enthält:

Der erste Gedanke wäre vielleicht, nun die Datenbank auf der Basis einer einfachen Tabelle zu erstellen und in den Spalten Dozent, Kurse, Teilnehmer und Raumnummern die entsprechenden Informationen einzutragen. Wenn wir das mit ein paar einfachen Datensätzen durchspielen, sehen wir jedoch bald, wo bei diesem Datenmodell das Problem liegt. Werfen Sie einen Blick auf Tabelle 6.1.

Name des Dozenten

Kurse

Teilnehmer

Raumnummern

Hr. Müller

Chemie I

Chemie II

Franz Feinbein

Lieschen Müller

Otto Döderlein

112, 113

Hr. Müller

Mathematik I

Otto Döderlein

Karl Kraut

Rosie Rüstig

010, 314, 112

Fr. Meier

Psychologie im Alltag

Hans Holbein

Anna Lieblich

Susi Söhnlein

212, 112, 322

Tabelle 6.1: Tabellarische Aufbereitung der gewünschten Informationen

Wie Sie sehen, lassen sich mit dieser Tabelle die vorhandenen Daten zwar bequem erfassen, aber die Art der Erfassung macht sie nicht besonders tauglich für praktische Zwecke. Nehmen wir beispielsweise an, Sie möchten herausfinden, welche Kurse ein bestimmter Teilnehmer besucht. Dazu müssten Sie alle Dozenten durchgehen und die Spalte Teilnehmer überprüfen. Das ist in höchstem Maße Zeit raubend und ineffektiv. Um unser Suchverfahren optimieren zu können, müssen wir unseren Datenbestand normalisieren. Zu diesem Zweck werden wir uns heute mit der ersten, zweiten und dritten Normalform auseinander setzen. Es gibt zwar noch weitere Normalformen, doch die ersten drei sind die wichtigsten. Mit jedem Schritt wird ein höherer Grad der Normalisierung erreicht.

Erste Normalform

Um Daten in eine Normalform zu bringen, muss man sie in Entitäten zusammenfassen. Wir beginnen mit der Entität Dozent, unter der wir die Attribute Namen der Dozenten, Kurse, Teilnehmer, Raumnummern ablegen. Abb. 6.1 zeigt die grafische Darstellung der Entität Dozent. Um unser Datenmaterial vollständig zu normalisieren, müssen wir unserem Datenbankmodell noch weitere Entitäten hinzufügen. Am Schluss wird es nicht mehr viel gemeinsam haben mit unserem momentanen Modell.

Abbildung 6.1:  Die Basisentität Dozent nach dem Ausgangsdatenmodell

Die erste Normalform verlangt, dass alle Entitäten eindeutig sein müssen und alle Attribute nur einfache Attributwerte aufweisen, also nicht mehrfach vorkommen dürfen. Um herauszufinden, ob sich Attribute wiederholen, überprüfen wir einfach, ob irgendwelche Attribute im Plural stehen. Und da haben wir gleich mehrfach Anlass, uns am Kopf zu kratzen:

All diese Attribute wiederholen sich und dürfen daher nicht in der Entität Dozent enthalten sein, wenn wir unsere Daten in die erste Normalform bringen wollen. Zu diesem Zweck müssen wir diese Attribute herunterbrechen und in ihrer eigenen Entitätentabelle erfassen. Ferner müssen wir überprüfen, ob alle Attribute in die kleinsten sinnvollen Entitäten aufgesplittet worden sind. So sollten Namen z.B. in Vornamen und Nachnamen aufgeteilt werden. Abb. 6.2 zeigt unsere neue Sammlung von Entitäten, die auch gleich um ein paar Attribute erweitert wurden.

Abbildung 6.2:  Sich wiederholende Attribute erhalten ihre eigene Tabelle.

Wir haben jetzt also vier verschiedenen Tabellen: Dozent, Kurs, Teilnehmer, Raum. Und weil's grad so schön war, habe ich die Entitäten gleich um ein paar Attribute erweitert:

Dozent - vname, nname, status, gehalt
Kurs - bezeichnung, zeit, thema, level
Teilnehmer - vname, nname, alter, level
Raum - nummer, plaetze, einrichtung

Jede Entität ist nun eindeutig und enthält keine sich wiederholenden Attribute. Die Entitäten enthalten sich aber nur selbst und haben keine Beziehung zueinander. Somit können wir aus diesem Datenmodell immer nur die Informationen beziehen, die innerhalb einer Entität abgelegt sind. Damit hat dieses Modell allerdings keinen besonderen praktischen Wert für uns. Um nun die Daten zueinander in Beziehung zu setzen, brauchen wir Identifikationsschlüssel.

Lassen Sie uns die einzelnen Entitäten der Reihe nach dahingehend untersuchen, was wir als Identifikationsschlüssel verwenden können.

Die Entität »Dozent« muss irgendwie adressiert werden können. Der erste Gedanke wäre vielleicht, die Namen der Dozenten als Identifikationsschlüssel zu verwenden. Aber, so muss man sich fragen, ist dieser Wert immer eindeutig und unveränderlich? Da es sich um Personennamen handelt, muss diese Frage mit Nein beantwortet werden. Selbst wenn dieser Fall aller Wahrscheinlichkeit nach nie eintritt, darf die potenzielle Möglichkeit dennoch nicht gegeben sein, damit das Datenmodell korrekt ist. Aus diesem Grund müssen wir für die Entität Dozent einen eindeutigen Identifikationsschlüssel einführen. Wir tun das mit dem Attribut persNr, also einer Personalnummer. Das kann ein beliebiger Wert sein, solange er eindeutig ist. Die meisten Datenbanken verfügen über eine Autowert-Funktion, die an jeden neuen Datensatz automatisch eine neue Nummer vergibt, sodass die Datensätze fortlaufend durchgezählt werden. In Abb. 6.3 sehen Sie die normalisierte Form der Entität Dozent. Bei der grafischen Darstellung von Datenmodellen werden die Attribute, die als Identifikationsschlüssel dienen, in geeigneter Form optisch hervorgehoben.

Die Entität Kurs ist ähnlich problematisch wie die Entität Dozent. Vermutlich werden mehrere Kurse mit derselben Bezeichnung angeboten und finden vielleicht sogar parallel statt. Also brauchen wir auch für die Entität Kurs einen Identifikationsschlüssel. Am leichtesten lösen wir dieses Problem, indem wir für jeden Kurs eine eigene Kursnummer vergeben. Da die meisten Kurse sowieso schon eine Nummer haben, brauchen wir uns hier nicht übermäßig verausgaben. Wenn Sie versuchen, einen Datenbestand zu normalisieren, werden Sie auf Informationen stoßen, die Sie bei der Erstellung des Ausgangsdatenmodells zunächst außer Acht gelassen haben, oder auf andere Daten, die sich nun als plötzlich sehr nützlich erweisen und darum in die Datenbank aufgenommen werden sollten. Mit der Vergabe einer Kursnummer ist die Entität Kurs in der ersten Normalform, zu sehen in Abb. 6.4.

Abbildung 6.3:  Die Entität Dozent in der ersten Normalform

Abbildung 6.4:  Die Entität Kurs wird über die Kursnummer eindeutig identifiziert.

In unserem Ausgangsdatenmodell waren die Kursteilnehmer nur »Menschen zweiter Klasse«, denn der einzige Weg, über die Teilnehmer etwas herauszufinden, führte über die Entität Dozent. Erfassen wir die Teilnehmer nun in einer eigenen Entität und damit in einer eigenen Tabelle, können wir mit jedem Datensatz noch zusätzliche Informationen speichern. Wie bei der Entität Dozent haben wir auch hier das Problem, dass Teilnehmer denselben Namen haben können, und die Wahrscheinlichkeit ist sogar größer, da es ja mehr Teilnehmer als Dozenten gibt. Wie bei den Dozenten vergeben wir auch für die Teilnehmer Nummern, um sie eindeutig identifizieren zu können. Heraus kommt die erste Normalform der Tabelle Teilnehmer, zu sehen in Abb. 6.5.

Abbildung 6.5:  Wie bei der Entität Dozent können auch bei der  Entität Teilnehmer Namen mehrfach vorkommen.

Die letzte Entität, die adressiert werden muss, ist die Entität Raum. Mit unserer gegenwärtigen Festlegung haben wir Glück. Da sich ein Raum über seine Raumnummer eindeutig von allen anderen Räumen des Gebäudes unterscheiden lässt, sind wir schon am Ziel unserer Bestrebungen. Sollte sich die Volkshochschule jedoch entschließen, ihre Kurse auf mehrere Veranstaltungsorte zu verteilen, bekämen wir Schwierigkeiten. Wir wollen es aber heute nicht allzu schwer machen und gehen darum davon aus, dass alle Kurse im selben Gebäude stattfinden. Eine vielleicht nicht ganz realistische Annahme, darum können Sie im Übungsteil zu dieser Lektion das Datenmodell dahingehend anpassen, dass die Kurse auf mehrere Veranstaltungsorte verteilt werden. Die endgültige Form der Entität Raum sehen Sie in Abb. 6.6.

Abbildung 6.6:  Die Entität Raum ist bereits in der Normalform.

Nachdem alle Entitäten in die erste Normalform gebracht sind und eindeutige Identifikationsschlüssel besitzen, können wir daran gehen, die Beziehungen zwischen den einzelnen Entitäten zu definieren. So erhalten wir ein klareres grafisches Datenmodell und können eventuelle Inkonsistenzen besser lokalisieren.

Nehmen wir zum Beispiel die Entitäten Kurs und Raum. Sehen Sie sich die verschiedenen Entitäten an und versuchen Sie, die einzelnen Entitäten mit dem Verb »hat« in Beziehung zu setzen. Im Falle von Kurs und Raum ergäbe das: »Jeder Kurs hat einen Raum«. Auf diesem Weg haben wir unsere erste Beziehung ermittelt.

Nach unserem Datenmodell lassen sich die nachstehend aufgeführten Beziehungen ermitteln (grafisch dargestellt in Abb. 6.7):

Abbildung 6.7:  Die Beziehungen innerhalb unseres aktuellen Datenmodells. Nicht unproblematisch!

Mit der Teilnehmer/Kurs-Beziehung sind wir etwas in die Bredouille geraten. Es handelt sich hier um eine Viele-zu-viele-Beziehung, die wir in zwei getrennte Eins-zu-viele- Beziehungen aufbrechen müssen. Hierzu müssen wir eine dritte Entität einfügen, die zwischen den beiden anderen Entitäten sozusagen den Vermittler spielt. Diese neue Entität muss zu den beiden anderen Entitäten in einer 1:n-Beziehung stehen. Im Falle der Entitäten Teilnehmer und Kurs könnten wir die Entität Platznummer einführen und damit den Platz des Teilnehmers in einem bestimmten Kurs definieren.

Damit lösen wir unser m:n-Problem, denn ein Sitzplatz kann nicht von mehr als einem Teilnehmer gleichzeitig besetzt werden, noch können Sitzplätze von mehreren Kursen auf einmal belegt werden. Wir fügen die neue Entität mitsamt ihren Beziehungen in unser grafisches Datenmodell ein und erhalten das in Abb. 6.8 gezeigte Schema.

Na, das war jetzt doch Einiges an Gehirnakrobatik. Sie fragen sich vielleicht, was der ganze Aufwand soll, nur um eine simple Datenbank zu entwerfen. Aber - so lehrt die Erfahrung - die Mühe, die Sie in die Entwurfsphase stecken, erspart Ihnen später Einiges an Zeit und Arbeit. Ohne Fleiß gibt's nun mal keinen Preis.

Die zweite Normalform

Der Weg zur ersten Normalform war hie und da mit Steinen gepflastert. Im nächsten Schritt müssen wir die Entitäten in die zweite Normalform bringen. Um die Bedingungen für die zweite Normalform zu erfüllen, müssen die Entitäten in einer Form definiert werden, die ermöglicht, dass die einzelnen Attribute (mit Ausnahme des Identifikationsschlüssels) allein vom jeweiligen Identifikationsschlüssel abhängen.

Kommen z.B. bestimmte Attribute in verschiedenen Datensätzen einer Entität mehrfach vor, sind also identisch, so sind sie nicht vollständig von einem Identifikationsschlüssel abhängig. Ein Weg, das herauszufinden, ist sich zu fragen: »Wenn sich ein Datum in diesem Datensatz ändert, muss ich es dann in anderen Datensätzen dieser Entität ebenfalls ändern?« Überprüfen Sie unter diesem Gesichtspunkt die verschiedenen Attribute der Entitäten, die wir in unserem Datenmodell aufgestellt haben. In allen Fällen sind sämtliche Attribute von einem Identifikationsschlüssel abhängig. Jeder Datensatz einer Entität kommt nur einmal vor.

Die dritte Normalform

Bringt man Daten in die zweite oder dritte Normalform, stößt man immer wieder mal auf Daten, die noch nicht in das Datenmodell integriert sind. Die dritte Normalform bietet weniger Verständnisschwierigkeiten als die zweite. Um die Bedingungen für die dritte Normalform zu erfüllen, muss die Entität bereits in die zweite Normalform gebracht sein und darf keine Attribute enthalten, die in irgendeiner Form voneinander abhängig sind (mit Ausnahme vom ID-Schlüssel). Solche Fälle lassen sich gewöhnlich leicht einkreisen. So gibt es z.B. bei unserer Entität Kurs eindeutig Probleme mit der dritten Normalform.

Die Entität Kurs hat die Attribute Name und Thema. Diese beiden Attribute hängen offensichtlich zusammen, also müssen wir die Entität modifizieren, um sie in die dritte Normalform zu bringen. Zu diesem Zweck führen wir eine neue Entität Thema ein, die den Namen des Kurses und sein Thema aufnimmt. Da mehrere Kurse dieselbe Bezeichnung und dasselbe Thema haben können, besteht zwischen Thema und Kurs eine 1:n-Beziehung. Abb. 6.9 zeigt das endgültige Datenmodell.

Unser Datenmodell umfasst nun die folgenden Entitäten:

Diese Entitäten und die Beziehungen, die zwischen ihnen bestehen, sind alles, was Sie brauchen, um Datenbanken für dynamische Websites anzulegen.

Vom Entwurf zur Datenbank

Haben wir unser Datenbankmodell auf dem Papier konzipiert, ist die Datenbank selbst damit noch nicht vollständig definiert. Wir müssen unsere Informationen noch irgendwie aufbereiten, um die physikalische Datenbankstruktur anlegen zu können. Diese Struktur ist den Entitäten nicht unähnlich, die wir definiert haben, aber wir müssen noch Mittel und Wege finden, wie wir die Beziehungen zwischen ihnen beschreiben. Die Definition mehrerer Tabellen mit den gewählten Attributen reicht offensichtlich nicht aus, um diese Tabellen untereinander zu verknüpfen. Hierzu müssen wir uns noch mit dem Konzept der Schlüssel auseinander setzen.

Abbildung 6.9:  Nun ist unser Datenmodell in  der dritten Normalform.

Datenschlüssel definieren

Um unser Datenbankmodell zu komplettieren, brauchen wir noch so genannte Schlüssel, von denen es zwei verschiedene Typen gibt. Der erste ist der so genannte Primärschlüssel, den wir schon kennen gelernt haben, als wir den Identifikationsschlüssel der einzelnen Entitäten definiert haben. Über den Primärschlüssel kann das Datenbanksystem Datensätze eindeutig erkennen.

Mit der Definition eines eigenen Schlüssels für jeden Datensatz haben wir eigentlich nichts anderes getan, als jeder Entität ein weiteres, eindeutiges Feld hinzuzufügen. Es wäre aber auch eine andere Vorgehensweise denkbar, vor allem dann, wenn eine Entität auf der »n-Seite« einer 1:n-Beziehung steht. Man kann nämlich verschiedene Attribute einer Entität sozusagen gruppieren und als Primärschlüssel definieren. Ein Beispiel: Der Nachname einer Person kann mehrfach vorkommen und ist daher kein eindeutiges Merkmal, könnte es aber in Verbindung mit anderen Attributen werden. So ist es höchst unwahrscheinlich, dass der Name einer Person in Kombination mit Anschrift und Geburtsdatum nicht eindeutig ist.

Primärschlüssel haben wir also schon verwendet und sie stellen auch kein Verständnisproblem dar. Die zweite Art von Schlüssel, die wir brauchen, ist der so genannte Fremdschlüssel. Mit ihm kommt Bewegung in unsere träge Datenmasse, denn er definiert die Beziehungen zwischen den verschiedenen Entitäten. Der Fremdschlüssel ist nichts anderes als der in einer Entität gespeicherte Primärschlüssel einer anderen Entität. Er macht die Beziehung zwischen diesen beiden Entitäten sozusagen amtlich.

Für alle Beziehungen muss auf der »n-Seite« einer Beziehung ein Fremdschlüssel festgelegt werden. Für unser Datenmodell haben wir die folgenden Beziehungen definiert:

In all diesen Fällen muss die »n-Seite« den Primärschlüssel der »1-Seite« erben. Wird ein Primärschlüssel in einer anderen Tabelle gespeichert als in der, in der er definiert wurde, spricht man von ihm als Fremdschlüssel. So müssen wir z.B. in der Entität Kurs das Attribut Raumnummer mit speichern, das wir von der Entität Raum übernehmen. Damit werden die 1:n-Beziehungen der Entität komplettiert. Diesen Schritt müssen wir für alle anderen Entitäten ebenfalls durchführen.

Wenn Sie möchten, können Sie das jetzt durchspielen. Abb. 6.10 zeigt das endgültige grafische Modell unserer Datenstruktur. An diesem Punkt haben wir die Daten so weit geordnet, dass wir sie als saubere SQL-Datenbank anlegen können.

Abbildung 6.10:  Das endgültige Datenbankmodell

Die fertige SQL-Datenbank

In einer späteren Lektion (Tag 12, »Komplexe Datenbankabfragen«) werden Sie etwas über die Datenbank-Abfragesprache SQL lernen. Im Moment wollen wir uns mit einem Blick darauf begnügen, wie unser Datenbankmodell in SQL aussieht. Die Entitäten unseres Modells bilden die Tabellen der Datenbank, die einzelnen Attribute werden zu den Feldern der Tabelle. Es dürfte nicht schwer fallen, die Bezüge zwischen Modell und SQL nachzuvollziehen.

create table raumTbl (
raumNr int not null,
plaetze int,
einrichtung varchar(50),
primary key (raumNr)
)
create table dozentTbl (
persNr int not null,
vname varchar(25),
nname varchar(25),
status varchar(50),
gehalt int,
primary key (persNr)
)
create table kursTbl (
kursNr int not null,
thema varchar(50),
persNr int,
raumNr int,
time time,
level int,
primary key (kursNr)
)
create table themaTbl (
name varchar(50) not null,
thema varchar(250),
primary key (name)
)
create table teilnTbl (
teilnNr int not null,
vname varchar(25),
nname varchar(25),
alter int,
level int,
primary key (teilnNr)
)
create table platznrTbl (
sitzNr int not null,
teilnNr int,
kursNr int,
primary key (sitzNr)
)

Im Grunde ist daran nichts Geheimnisvolles. Interessant ist ein Vergleich des endgültigen Datenbankmodells mit unserem Ausgangsmodell. Statt einer einzigen Tabelle mit einem Wust von teils redundanten Daten haben wir nun ein logisch strukturiertes Modell von sechs Tabellen.

6.5 Zusammenfassung

Um dynamische, datenbankgestützte Websites zu erzeugen braucht es etwas mehr als nur UltraDev zu öffnen und dann einfach loszulegen. Sie sollten reichlich Zeit auf die Planungsphase verwenden. Es ist effektiver, zunächst einmal auf einem Blatt Papier die komplette Datenbankstruktur zu entwerfen, statt gleich am Programmcode zu stricken und dann festzustellen, dass man die Datenbank nochmal völlig neu konzipieren muss.

Bestimmte HTML-Dokumente lassen sich besonders gut dynamisch machen:

Eine Sitemap zu zeichnen und die künftige Site auf diese drei Kategorien hin zu überprüfen sind die ersten Schritte in der erfolgreichen Planung einer dynamischen Webanwendung.

Haben Sie alle Informationen vorliegen, die Sie zur Erstellung einer Site benötigen, können Sie ein Datenmodell entwerfen. Das Verfahren, mit dem das Datenmodell um redundante Daten bereinigt wird, bezeichnet man als Normalisierung.

Es gibt drei Normalisierungsschritte, die man einhalten sollte, damit das Datenmodell problemlos in eine tatsächliche Datenbank übersetzt werden kann.

Die erste Normalform definiert die Entitäten, mit denen das Modell arbeitet, sowie die entsprechenden Attribute. Damit wird ferner sichergestellt, dass die Attribute nur einmal vorkommen und sich wiederholende Attribute in einer eigenen Tabelle abgelegt werden. Sind die Entitäten definiert, muss geklärt werden, welche Beziehungen zwischen ihnen bestehen. Beziehungen werden graduell eingestuft: 1:1, 1:n, m:n.

Die zweite Normalform setzt voraus, dass die Daten bereits in die erste Normalform gebracht sind. Ferner dürfen Attribute ausschließlich vom Identifikationsschlüssel des jeweiligen Datensatzes abhängig sein.

Für die dritte Normalform müssen die Entitäten in der zweiten Normalform vorliegen. Zusätzlich muss eine weitere Anforderung erfüllt sein. Hängen Attribute nicht ausschließlich vom Identifikationsschlüssel, sondern von anderen Attributen ab, müssen sie in einer eigenen Tabelle abgelegt werden, damit die Bedingungen für die dritte Normalform erfüllt sind.

Der letzte Schritt im Datenbankentwurf besteht in der Anlage der Datenbankstruktur selbst. Die Struktur der Datenbank beruht auf dem fertig ausgearbeiteten Datenbankmodell, muss aber noch um die Informationen ergänzt werden, in welcher Beziehung die Entitäten zueinander stehen.

6.6 Fragen und Antworten

Frage:
Was ist der Hauptgrund für den Einsatz von datenbankgestützten Websites?

Antwort:
Das Hauptargument für eine Datenbankanbindung ist die Effizienz. Allzu oft ist das Argument für den Einsatz einer bestimmten Technologie die bloße Verfügbarkeit, nicht tatsächliche praktische Erfordernisse oder Notwendigkeiten. Sie sollten Datenbanken nur dann einsetzen, wenn es die Website um sinnvolle Funktionen bereichert und die Betreuung vereinfacht - nicht, weil es gerade »hipp« ist.

Frage:
Wie kann man mit einer Datenbank eine leichter bedienbare Oberfläche für eine Webseite erstellen, als das mit HTML-Mitteln möglich wäre?

Antwort:
Vielleicht wundern Sie sich, wieso eine datenbankgestützte Website »pflegeleichter« sein soll als eine auf reinem HTML-Code basierende Site. Wenn Sie eine Datenbank wie MS Access verwenden oder eine Programmiersprache wie RealBASIC, können Sie eine Eingabemaske erstellen, die genauso leicht zu bedienen ist wie eine beliebige Office-Anwendung.

Frage:
Kann ich Datenbanken auch erstellen, ohne die Daten vorher zu normalisieren?

Antwort:
Das geht zwar, aber ich würde es nicht empfehlen. Die Normalisierung von Daten führt zu einem effizienten Datenmodell ohne Redundanzen. In manchen Fällen ist ein gewisses Maß an Redundanz vertretbar, und Sie können auf den Prozess der Normalisierung verzichten. Wollen Sie aber professionelle Sites erstellen, möchte ich Ihnen dringend raten, sich die Zeit zu nehmen und die Daten sauber zu normalisieren.

Frage:
Mit welchen Problemen muss ich rechnen, wenn ich Daten nicht normalisiere?

Antwort:
In diesem Fall müssen Sie damit rechnen, dass Sie wirklich viel Zeit damit aufwenden müssen, um Ihren Datenbestand zu aktualisieren. Nicht normalisierte Datenbanken weisen Redundanzen auf. Somit ist es unmöglich, exakte Suchabfragen zu formulieren. Eine Aktualisierung ist ebenfalls sehr aufwändig, da Sie pro Änderung immer mehrere Datensätze aktualisieren müssen. Bei fünf oder sechs Datensätzen ist das noch kein Problem. Aber, wie Sie sich vorstellen können, wächst die benötigte Zeit mit der Anzahl der Datensätze.

6.7 Workshop

Der Workshop dient dazu, den gelesenen Stoff mithilfe von gezielten Fragen und Übungen zu vertiefen. Die Antworten finden Sie in Anhang A, »Quiz-Antworten«.

Quiz

  1. Welche Teile einer Website lassen sich am besten dynamisieren?
  2. Was bewirkt die Normalisierung einer Datenbank?
  3. Was ist die erste Normalform?
  4. Was ist die zweite Normalform?
  5. Was ist die dritte Normalform?
  6. Was versteht man unter einem Primärschlüssel?
  7. Was versteht man unter einem Fremdschlüssel?

Übungen

  1. Zeichnen Sie Sitemaps von Sites, die Sie erstellt haben oder erstellen wollen. Welche Bereiche ließen sich mit Datenbankanbindung effizienter gestalten? Konzentrieren Sie sich dabei nicht nur auf solch offensichtliche Punkte wie Personaldaten oder Video- archive. Suchen Sie nach Informationen, die sich zur Manipulation per Datenbank anbieten.
  2. Erstellen Sie ein Datenmodell für einen Spielzeugladen mit den Daten aus Tabelle 6.2 und bringen Sie sie in die dritte Normalform. Der Spielzeugladen möchte diese Datenbank für Mailingaktionen verwenden und Kunden anschreiben, die ähnliche Artikel bereits gekauft haben.

Artikel

Preis

Käufer

Kategorie

Riesen-Rad

320,00 DM

Lisa Fröhlich,

Heinz Kopf,

Emma Maier

Räder,

Kleinkinder

Toller Flieger

75,00 DM

Emma Maier,

Jule Huber,

Sven Moser

Jugendliche,

Flugzeuge

Murmeln

5,00 DM

Kurt Knobel,

Paul Grüblein,

Susi Sommer

Kleinkinder,

Jugendliche,

Erwachsene,

Diverses

Tabelle 6.2: Schreiben Sie ein normalisiertes Datenmodell für diesen Spielzeugladen



vorheriges KapitelInhaltsverzeichnisStichwortverzeichnisFeedbackKapitelanfangnächstes Kapitel


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