Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs

Strukturierter Aufbau in der ASP-Programmierung

Geschrieben von: Rene Drescher-Hackel
Kategorie: ASP Grundlagen

This printed page brought to you by AlphaSierraPapa

Im heutigen Artikel möchte ich Ihnen zeigen, daß es sinnvoll sein kann, seinen ASP-Dateien mehr "Struktur" zu verleihen. Der Artikel wird Ihnen zeigen, wie Sie selbst bei übermäßig vielen Programmzeilen immer noch den Überblick behalten.

In meiner täglichen Praxis erlebe ich immer wieder, wie wichtig es ist, sauber und übersichtlich zu programmieren. Fast jeder von Ihnen wird immer öfter mit Arbeiten konfrontiert, die vor Monaten - oder Jahren - einmal fertiggestellt wurden. Wer will da noch die genauen Überlegungen kennen, die einst bei der Scripterstellung leitend waren.

ASP-Einsteigern soll der Artikel dazu dienen, von Anfang an auf eine saubere und übersichtliche Programmierung zu achten und zeigen, wie man dies unter anderem erreichen kann.

Allgemeiner Aufbau der Seite

Der erste Eintrag auf der ASP-Seite ist

<%@ Language=VBScript %>

wenn VBScript die von Ihnen bevorzugte Script-Sprache ist.

Sie sollten auf gar keinen Fall die erste Zeile umbrechen und innerhalb der ersten Begrenzungszeichen weiteren Code unterbringen. Dies führt regelmäßig zu folgender Fehlermeldung:

Active Server Pages- Fehler 'ASP 0221' 
Ungültige @ Kommandozuweisung

Als nächstes folgen daher wieder die typischen Script-Begrenzungszeichen:

<%
...
%>

Innerhalb dieser Begrenzungszeichen steht dann der eigentliche Code.

Ihr nächster Eintrag sollte dann die Anweisung

Option Explicit

sein. Diese Anweisung "zwingt" Sie dazu, daß Sie Ihre im Script später benutzten Varaiablen vor ihrer ersten Verwendung deklarieren, also bekannt machen. Dies macht aus zweierlei Gründen Sinn: Zum einen wissen Sie beim ersten Lesen Ihres Scriptes später, welche Variablen Sie alle benutzen. Zum anderen ist der Zugriff auf deklarierte Variablen schneller, da hier über die Ordinalzahl (der Variable) auf sie zugegriffen wird, während im anderen Fall über den Varaiablennamen der Zugriff erfolgt.

Die Variablendeklarationen können dabei mit

Private | Public | Dim Variablenname

erfolgen. Es empfiehlt sich dabei, die einzelne Anweisung gleichzeitig zu kommentieren:

Dim strName    ' Name des Benutzers

Ein weiterer Punkt ist die Namensgebung bei der Variablenbenennung. Ich empfand es bislang als äußerst hilfreich, den von mir in der Variable erwarteten Variablentyp im Namen mit anzugeben. Wenn also der Typ "String" erwartet wird, dann wurde dem Variablennamen das Kürzel "str" voran gestellt. Beim Typ "Integer" dann "int", bei "Boolean" dann "bln" und so weiter. Darüber hinaus sollten Sie sich angewöhnen, sinnvolle Namen als Bezeichnung zu wählen. So kann die Variable für eine Kundennummer z.B. "intKundenNr" heißen, statt nur "KNR".

Wie oben für die Variablendeklaration schon angesprochen, sollten Sie Ihre Scripte kommentieren - das erhöht die spätere Lesbarkeit. Kommentare können dabei u.a. den dann folgenden Scriptblock näher beschreiben oder gar nur eine einzelne Anweisung näher erläutern.

Häufig wiederkehrende Anweisungen in Prozeduren/Methoden verpacken

Stellen Sie sich vor, sie müssen aus diversen Datenbanktabellen verschiedene Informationen zusammentragen und in einer SELECT-BOX darstellen. Es wäre müßig, jedes Mal den selben Codeabschnitt neu zu verfassen.

Hier kann man sich die Arbeit dadurch erleichtern, in dem man immer wiederkehrende Programmteile in einzelne Prozeduren verpackt. Dabei können Sie zwischen

Private | Public Sub | Function ([parameter]) 

wählen.

Ob Sie nun "Sub" oder "Function" wählen hängt ganz davon ab, was Sie von Ihrer Prozedur erwarten. Soll ein bestimmter Codeblock nur abgearbeitet werden, so ist "Sub" die richtige Wahl. Möchten Sie aber durch den Aufruf der Prozedur einen Wert zurück erhalten, dann ist Function die richtige Entscheidung. Hier wird also deutlich: Sub kann keine Werte zurück geben (mit einer Ausnahme, wie Sie weiter unten noch sehen werden) - Function schon.

Die Prozedur bzw. Methode wird durch die Angabe des Gültigkeitsbereiches (Private oder Public) , der Methodenart (Sub oder Function) und der an die Prozedur zu übergebenden Parameter gekennzeichnet. Die Angabe von Parametern ist optional. Sind keine Parameter zu übergeben, entfällt also diese Angabe. Hier ist jedoch noch zu beachten: Übergeben Sie Parameter an die Prozedur immer " ByVal " (Wertübergabe). Dies hat den Vorteil, daß innerhalb der Prozdur der Wert der Variablen sich ändern kann, jedoch außerhalb der Prozedur der ursprüngliche Variablenwert erhalten bleibt. Wollen Sie jedoch gerade diesen Umstand bezwecken, daß sich aufgrund des Prozeduraufrufes die an die Prozedur übergebene Variable sich mit ändert, lassen Sie den Zusatz "ByVal" weg. Standardmäßig werden Variablen an Prozeduren "ByRef" übergeben.

Das Ende einer Prozedur wird mit der Anweisung

End Sub | Function

gekennzeichnet. Ist es erforderlich die Prozedur vorzeitig zu verlassen, so erfolgt dies mit

Exit Sub | Function

Schauen wir uns das ganze mal an einem Beispiel an - einer dynamisch erzeugten SELECT-BOX. Der Code hierfür könnte wie folgt aussehen:

Public Sub meineSelectBox(ByVal strTable, ByVal strColumn, ByVal strElement)
    ' Prozedur erzeugt anhand der übergebenen Werte für
    ' Tabelle, Spalte und Elementname eine Select-Box
    Dim strTemp         ' Temporärvariable
        strTemp = "<select name=" & strElement & ">"
        strTemp = strTemp & "<Option value=0 >Bitte wählen Sie</Option>"
        ' Datenbankteil
        ' SQL-Abfrage
        Dim sql
        sql = " SELECT id, " & strColumn & " FROM " & strTable & " "
            call dbconnect()    ' Datenbankverbindung herstellen
                set rs = conn.Execute(sql)
                    if rs.eof then
                        ' Prozedur vorzeitig verlassen
                        ' und nur Textfeld ausgeben
                        Response.Write "<input type=text name=" & strElement & ">"
                        call dbclose()	' Datenbankverbindung vorher schließen
                        Exit Sub    ' Prozedurende
                    else
                    while not rs.eof
                        strTemp = strTemp & "<Option value=" & rs(0) & ">" & rs(1) & 
                            "</Option>"
                        rs.MoveNext
                    wend
                    end if
                call dbclose()      ' Datenbankverbindung schließen
            strTemp = strTemp & "</select>"
            ' SelectBox ausgeben
            Response.Write strTemp
End Sub

Nach der einleitenden Kommentierung erfolgt zunächst die Deklarierung einer lokalen Variable strTemp. Dies ist insoweit vorteilhaft, als daß der Zugriff auf lokale Variablen (also solchen, die innerhalb von Prozeduren deklariert werden), wieder schneller ist, als der Zugriff auf globale (außerhalb von Prozeduren deklarierte) Variablen. Für die Datenbankverbindung ist es jedoch ratsamer die Variable "conn" global zu deklarieren, damit andere Prozeduren das conn-Objekt nutzen können. Dabei sollten Sie beachten, daß im Fall der "conn"-Variable, diese PUBLIC deklariert werden sollte.

Dann folgt der erste Teil der Select-Box. Dadurch, daß der Elementname mitübergeben wurde, kann die Select-Box mit jedem Aufruf der Prozedur einen beliebigen Namen bekommen, sodaß am Ende dieselbe Prozedur auf ein und derselben Seite mehrfach aufgerufen werden kann und dennoch immer wieder (namentlich) verschiedene HTML-Elemente erzeugt werden.

Jetzt folgt die SQL-Anweisung. Auch hier ist die SQL-Anweisung so formuliert, daß sie am Ende variabel einsetzbar ist. Hierbei wurde jedoch davon ausgegangen, daß die abzufragende Tabelle über eine Primärschlüsselspalte mit der Bezeichnung "id" verfügt. Dies ist dann für die Wertzuweisung im Option-Value hilfreich. An das SQL-Statement wird die auszulesende Spalte und Tabelle übergeben. Dadurch ist es wieder möglich jede x-beliebige Tabelle/Spalte auszulesen und das Ergebnis in einer Select-Box darzustellen.

Sofern kein Datensatz gefunden wurde, wird - um das HTML-Design nicht zu zerstören - ein einfaches Textfeld ausgegeben und die Prozedur vorzeitig verlassen.

Ist ein Datensatz vorhanden, so werden die Option-Einträge der Select-Box erzeugt. An dieser Stelle kommt uns der Primärschlüssel des ausgelesenen Datensatzes zu gute. Um dem value nicht eine unnötig lange Zeichenkette zuzuweisen, wird hier einfach ein Integer-Wert - die Datensatz-ID - zugewiesen.

Abschließend wird die HTML-Anweisung komplettiert und ausgegeben.

Das ganze ließe sich mit einer Function genauso realisieren. Lediglich die erste und die letzten beiden Zeilen würden sich ändern:

Public Function meineSelectBox(ByVal strTable, ByVal strColumn, ByVal strElement)
...
        meineSelectBox = strTemp
End Function

Damit die Function den Wert entsprechend zurückgibt, wird ihr der Wert von "strTemp" entsprechend zugewiesen. Die Ausgabe erfolgt dann mit dem Funktionsaufruf:

Response.Write meineSelectBox(...)

In den runden Klammern sind dann die Werte für die entsprechende Tabelle/Spalte und der Elementname an die Function mitzuübergeben.

Richtige Übergabe der Parameter an die Prozedur

Bei der Übergabe der Parameter an die Prozedur sollte folgendes beachtet werden:

Wie oben in unserem kleinen Beispiel schon zu sehen war, können die Parameter durch Voranstellen des Schlüsselwortes ByVal an die jeweilige Prozedur übergeben werden. ByVal bewirkt dabei, daß nur der Wert der Variablen übergeben wird. Arbeiten Sie innerhalb der Prozedur mit der gleichen Varaiablen weiter, so bleibt der Wert der Variablen außerhalb der Prozedur erhalten - gleich welchen Wert Sie der Variablen innerhalb der Prozedur zuweisen. Folgendes Codebeispiel soll Ihnen dies hier einmal verdeutlichen:

<%
dim a   ' Variable a
a=5     ' Wertzuweisung
Response.Write "Die Variable a= " & a & " vor Prozeduraufruf 
        <hr>" 'vor Prozeduraufruf
call meineProzedur(a)
Response.Write "Die Variable a= " & a & " nach Prozeduraufruf 
        <hr>" 'vor Prozeduraufruf

Public Sub meineProzedurByVal(ByVal a)
    Response.Write "Die Variable a= " & a & " in der Prozedur vor 
        Wertänderung <hr>"
    a=10        ' Wert ändern
    Response.Write "Die Variable a= " & a & " in der Prozedur nach 
        Wertänderung <hr>"
End Sub
%>

In diesem Beispiel wird der Variablen a der Wert 5 zu gewiesen. Dann erfolgt der Aufruf einer Prozedur, wobei die Variable a ByVal an die Prozedur übergeben wird. Um deutlich zu machen, wie sich eine Wertänderung innerhalb der Prozedur außerhalb dieser wieder auf a wertmäßig auswirkt, habe ich hier in der Prozedur a den Wert 10 zugewiesen. Die nachfolgende Grafik zeigt recht deutlich, welchen Wert a jeweils angenommen hat und wie sich ByVal in der Parameterübergabe auf den Wert der Variablen ausgewirkt hat.

Das Gegenstück zu ByVal ist ByRef. Hier wird die Adresse der Variable übergeben, so daß - das obige Beispiel entsprechend abgeändert - a den Wert aus der Prozedur automatisch übernimmt.

dim a   ' Variable a
a=5     ' Wertzuweisung
Response.Write "Die Variable a= " & a & " vor Prozeduraufruf <hr>" 'vor Prozeduraufruf
call meineProzedur(a)
Response.Write "Die Variable a= " & a & " nach Prozeduraufruf <hr>" 'vor Prozeduraufruf

Public Sub meineProzedurByRef(ByRef b)
    Response.Write "Die Variable a= " & a & " in der Prozedur vor Wertänderung <hr>"
    b=10        ' Wert ändern
    Response.Write "Die Variable a= " & a & " in der Prozedur nach Wertänderung <hr>"
End Sub

Um deutlich zu machen, wie ByRef sich verhält, habe ich jetzt die Prozedurvariable b eingeführt. Im Gegensatz zu dem vorangegangenen Beispiel habe ich hier b den Wert 10 zugewiesen. Dennoch hat sich der Wert von a geändert, wie die nachfolgende Grafik wieder zeigt:

Anders als bei PHP, erfolgt die Übergabe der Variablen standardmäßig - also ohne Angabe von ByVal oder ByRef - By Reference. Die Übergabe von Variablen ByRef an die Prozedur ist also dann sinnvoll, wenn der Variablenwert mit geändert werden soll. Daneben ist der Einsatz von ByRef wieder etwas schneller als ByVal.

Wenn man dabei ist, sich Gedanken zu machen wie und wann es am sinnvollsten erscheint ByVal oder ByRef einzusetzen, so möchte ich Ihnen noch folgenden Hinweis geben:

Gelegentlich kommt es vor, daß man mehr als einen Wert durch den Funktionsaufruf zurückgegeben haben möchte, eine Function aber andererseits nur einen Rückgabewert erlaubt. Wie kann man dem Abhelfen? Nun, Sie übergeben einfach eine zusätzliche Variable an die Funktion - allerdings diesmal bewußt ByRef. Da Sie nun wissen, wie sich der Wert der Variable ändern kann, die ByRef an die Funktion übergeben wurde, haben Sie auch zugleich den Weg, mehr als einen Wert aus einem Funktionsaufruf zurückzuerhalten. Und genau so könnten Sie mit einer Sub-Prozedur verfahren. Die Sub-Routinen geben nie einen Wert an die aufrufende Stelle zurück. Benötigen Sie aber gerade durch den Aufruf einer Sub einen bestimmten Rückgabewert, so übergeben Sie an die Sub einfach einen Wert ByRef. Das Ergebnis ist analog den obigen Ausführungen zur Function.

Private oder Public oder doch Dim?

Lassen Sie mich an dieser Stelle ein paar Ausführungen zum Unterschied der Schlüsselwörter Private und Public machen.

Beide Schlüsselwörter beschreiben den Geltungsbereich - sowohl der Prozedur als auch der einzelnen Variable. Hinsichtlich der Variablendeklaration sollten Sie folgende Überlegungen beachten:

  1. Wo benötige ich Zugriff auf die einzelne Variable?
    Benötigen Sie Ihre Variable lediglich innerhalb einer bestimmten Prozedur, so genügt es, wenn Sie diese mit der Anweisung Dim innerhalb der Prozedur definieren. Sie müssen jedoch beachten, daß diese Variable auch nur innerhalb der jeweiligen Prozedur gültig ist. Public und Private können innerhalb einer Prozedur nicht zur Variablendeklaration benutzt werden.
  2. Welchen Gültigkeitsbereich hat die Prozedur?
    Die Frage ist von Bedeutung, wenn Sie innerhalb von VBScript mit Klassen arbeiten. So sind Private deklarierte Variablen und Methoden nur innerhalb der Klasse verfügbar, jedoch nicht von außen (über das Objekt der Klasse) aufrufbar.

ASP-Logik kapseln

Wenn Sie denn so detailiert vorgehen und fast alles in Prozeduren verpacken, dann stellt sich die Frage, wie man am besten die ASP-Script-Logik zentral verfügbar (administrierbar) machen kann.

Dies erreichen Sie über ein entsprechendes INCLUDE der jeweiligen Logik-Seite.

<!--#include file="../meineLogik.asp"-->

Hierbei müssen Sie aber beachten, daß die Seite, in welcher der INCLUDE-Befehl steht, ebenfalls eine ASP-Seite sein muß. Dies ist dadurch begründet, da Sie ja hier die Prozedur aus der includierten Seite aufrufen wollen, was regelmäßig wie folgt geschieht:

<%
call meinProzedurname(meineParameter,...)
%>

Die call-Anweisung ist dabei nicht zwingend, bringt aber einen entscheidenen Syntax-Vorteil im Aufruf der Prozedur. Nehmen wir hier wieder das obige Beispiel der Select-Box. Hier haben wir uns für eine SUB-Prozedur entschieden. Der Aufruf dieser SUB-Prozedur ohne dem Schlüsselwort call müßte dann korrekter Weise folgendermaßen erfolgen:

MeineSelectBox  strTable, strColumn, strElement

Wenn wir nun call verwenden sieht das Ganze so aus:

call meineSelectBox(strTable, strColumn, strElement)

Sie sehen also, beim Einsatz von call ist es erforderlich, die übergebenen Parameter in runden Klammern zu fassen. Wäre unsere Prozedur als FUNCTION definiert worden, so müßten wir in jedem Fall die Parameter in entsprechender Umklammerung mit angeben.

Die Benutzung von call beim Prozeduraufruf hat also den Vorteil der einheitlichen Syntax - ich muß also nicht mehr darauf achten, ob ich nun eine SUB oder eine FUNCTION aufrufe - in jedem Fall werden die Parameter in runder Umklammerung an die Prozedur übergeben.

Des weiteren wird durch call im Script deutlich, daß an dieser Stelle eine Prozedur aufgerufen wird.

Zusammenfassung

Der Artikel soll insbesondere ASP-Einsteigern dazu dienen, von Anfang an darauf zu achten, sauber und übersichtlich - strukturiert - zu programmieren.

Durch den Einsatz von Prozeduren, lassen sich insbesondere mit Blick auf die Ressourcen, verschiedenste Programmteile gezielt ansteuern. So kann eine Datenbankverbindung z.B. erst dann angefordert werden, wenn diese auch explizit benötigt wird und sobald sie nicht mehr erforderlich ist, entsprechend wieder freigegeben werden.

Mit Prozeduren kann man seinen Code so gestalten, daß er weitgehend allgemeingültig bleibt, was die Wiederverwendbarkeit in anderen Projekten enorm erleichtert. Eine weitere Möglichkeit wäre auch Kapselung des Script-Codes in einzelne Klassen (Class ... End Class).

Durch die "Auslagerung" der einzelnen Prozeduren in eine eigenständige ASP-Datei kann man auch noch klarer Design und Programmierung voneinander trennen, was am Ende die Wartungsfreundlichkeit des ASP-Codes und die Zusammenarbeit der Abteilungen (Designer/Programmierer) enorm erleichtert.

This printed page brought to you by AlphaSierraPapa

Download des Codes

Klicken Sie hier, um den Download zu starten.
http://www.aspheute.com/code/20011112.zip

Verwandte Artikel

Überprüfen von HTML-Formularen mit ASP
http:/www.aspheute.com/artikel/20000522.htm
@-Direktiven auf ASP Seiten
http:/www.aspheute.com/artikel/20000405.htm
Auswertung von HTML Formularen mit ASP
http:/www.aspheute.com/artikel/20000406.htm
Dynamische Includes in ASP
http:/www.aspheute.com/artikel/20000706.htm
Einführung in Stringoperationen
http:/www.aspheute.com/artikel/20001003.htm
Einfache String Operationen
http:/www.aspheute.com/artikel/20000503.htm
Fehlerbehandlung richtig eingesetzt
http:/www.aspheute.com/artikel/20001011.htm
Global.asa: Verwendung, Events und Probleme
http:/www.aspheute.com/artikel/20001018.htm
Klassen in VBScript
http:/www.aspheute.com/artikel/20000526.htm
Session Variablen - Verwendung und Stolpersteine
http:/www.aspheute.com/artikel/20000505.htm

 

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.