Formatierung 0/10
Design und Technik
Wieso dieses Kapitel?
Sie denken jetzt warscheinlich, über Formatierung hätten Sie als Fortgeschrittener oder Profie doch bereits genug gelesen. Ich versuche dieses Kapitel möglichst kurz zu halten und hauptsächlich die Dinge zu erwähnen, die auch für Fortgeschrittene nicht unbedingt selbstverständlich sind. Außerdem geht es nicht nur um reine Formatierung.
Warum man Code formatiert ist wohl keine Frage. Spätestens wenn man mit Anderen zusammenarbeitet oder seinen Code veröffentlicht ist klar, wie wichtig Formatierungen sind. Auch sich selbst hilft man durch verständlichen Code.
Optimierung
Viele versuchen von vornherein den Code so optimiert wie möglich zu schreiben. Aber es ist immer leichter funktionierenden Code zu optimieren, als optimierten Code zu debugen. Deshalb sollten Sie erstmal zusehen, das der Code möglichst fehlerfrei läuft und sich erst dann auf Optimierungen stürzen. Vor allem lohnt es sich erstmal herauszufinden, welche Prozeduren denn beonders viel Zeit beanspruchen (das nennt sich profilen) und erst dann diese gezielt zu optimieren. So spart man sich manchmal unnötige Arbeit und außerdem ist unoptimierter Code meist leichter verständlich und somit besser wartbar.
Standards
Folgende Dinge haben Sie schon tausend mal gehört. Deshalb nur nochmal eine kurze Zusammenfassung: Aussagekräftige Namen, jedes neue Wort innerhalb eines Bezeichners mit einem Großbuchstaben beginnen (die sonst gebräuchiche aternative mit Unterstrichen lässt QB leider nicht zu) und möglichst eine einheitliche Konvention verwenden. Ungarische Notation ist out, also kein 'n' für integer, ein 's' für Strings, ... . Außerdem kann man in QB zur Not die verfügbaren Suffixe '%', '$', ... verwenden. Statt willkürlich nichts sagende Zahlenliterale zu verwenden (3.14159, ...), lieber zu Konstanten greifen (PI, ...). Verschachtelten Code dementsprechend einrücken, zusammengehörenden Code auch zusammenschreiben, nicht zusammengehörendes durch Leerzeilen trennen.
Komentare
Nein jetzt kommt nicht der Standard: Kommentiere so viel wie möglich, bla bla bla, sondern fast das Gegenteil. Verwende aussagekräftigen Code statt tonnenweise Komentare. Wenn ihr eine Variable 'n' nennt und dann Kommentiert, dass das der Name der Hauptfigur ist, hat niemand was davon. Wenn man den Code noch mal anuckt muss man erstmal zurück zur Deklaration und gucken für was dieses komische 'n' stand. Und vermeidet den typischen Anfängerfehler die Syntax zu beschreiben, statt die Semantik. Also nicht wie im folgenden Beispiel:
IF x > 0 THEN ' Wenn x größer 0 ist, mache ... ... END IF
Das was gemacht wird steht auch im Code, jedoch nicht das Warum und bei komplizierteren Aufgaben ist auch das Wie manchmal nicht ersichtlich.
Des weiteren gilt: Wenn Sie merkt, dass Sie ein Codefragment beonders stark komentieren müssen, Teilen Sie es in mehrere Prozeduren auf. Das verschafft Übersicht und der Code spricht mehr für sich selbst, so das viele Komentare entfallen können.
LadeDate "daten.txt", feld() Sortiere feld() GibFeldAus feld()
Wenn man das ließt versteht man ohne jedes Komentar, was gemeint ist. Bei folgendem hingegen nicht:
handle = FREEFILE OPEN "daten.txt" FOR INPUT AS handle i = 0 DO UNTIL EOF(handle) LINE INPUT #handle, feld(i) i = i + 1 LOOP CLOSE handle FOR i = 0 TO UBOUND(feld) - 1 FOR j = i TO UBOUND(feld) IF feld(i) < feld(j) THEN SWAP feld(i), feld(j) NEXT NEXT PRINT "|"; FOR i = 0 TO UBOUND(feld) IF LEN(feld(i)) > 5 THEN PRINT RIGHT$(feld(i), 5); ELSE PRINT SPACE$(5 - LEN(feld(i))) + feld(i); END IF PRINT "|"; NEXT PRINT
Hier noch gleich ein wenig Eigenwerbung: Der letzte Abschnitt ließe sich mit hilfe von MQB auch so formulieren:
PRINT "|"; FOR i = 0 TO UBOUND(feld) PRINT mqbTextAlign(STR$(feld(i)), 5); "|"; NEXT PRINT
Außerdem hätte man des weiteren den Vorteil, das man die Prozedur zum Sortieren und auch die zum Ausgeben von Datenfeldern auch für andere Aufgaben verwenden kann.
Bemerkung am Rande: Das hier verwendete Sortierverfahren ist zwar nicht das schnellst, aber das am leichtesten merkbare und zudem ist es extrem kurz. Bei einem besseren Sortierverfahren würde der Code noch wesentlich unübersichtlicher geraten.
Definition von Variablen
Früher (bis in die 90er) galt, man solle alle Variablen möglichst am Anfang einer Prozedur definieren. Heutzutage gilt das Prinzip, Variablen so nah wie möglich an ihrem Verwendungsort zu definieren. Dadruch ist wesentlich klarer, wozu die Variable überhaupt gebraucht wird. Außerdem müssen einige Variablen auf die Weise gar nicht erst angelegt werden. Wenn die Prozedur bereits beendet wird, bevor die Variable angelegt wird, kann das Anlegen auch keine Zeit benötigen.
Falls Sie streng nach Regeln der strukturierten Programmierung arbeiten, bringt ihnen der letzte keinen Vorteil, da eine Prozedur nach disen Regeln nur einen Austrittspunkt haben darf. Aber inzwischen programmiert sowieso fast niemand mehr rein strukturiert. Funktionen und Schleifen haben wieder beliebig viele Austrittspunkte. 'GOTO' wird aber immernoch, wenn irgendwie sinnvoll möglich, vermieden. (Das Verlassen verschachtelter Schleifen lässt sich leider in QB nicht andres lösen.) Zu 'GOTO' komme ich aber später nochmal.
Falls Sie die Angewohnheit haben möglichst viele Variablen mit einem 'DIM' zu definieren, sollten Sie versuchen sich das wieder Abzugewöhnen. Versuchen Sie zusammengehörendes mit einem 'DIM' zu erledigen, was jedoch nicht dazugehört bekommt ein eigenes 'DIM'. Dadruch ist klar zu erkennen, was zusammengehört und Sie müssen keine gigantischen Zeilen durchsuchen, wenn Sie eine bestimmte Variable suchen:
DIM x AS INTEGER, y AS INTEGER ' Aber DIM anzahl AS INTEGER DIM alter AS INTEGER
Ich personlich verwende stehts ein 'DEFINT A-Z' und definiere Laufwariable, die nur für eine Schleife gelten nicht extra.
GOTO
Wie Sie sicherlich schon of gehört haben und auch hier bereits erwähnt wurde ist GOTO etwas, das nach Möglichkeit vermieden werden sollte. Nach Möglichkeit heißt nicht das zwanghaft auf jeden Fall GOTO vermieden soll. GOTO ist aber ein Schlüsselwort, das nur extrem selten das ausdrückt, was man tun will. Wenn man eine Codeteil wiederholen will, sollte man auch eine Schleife verwenden, da sie genau für diee Aufgabe erfunden wurde. Wenn Sie eine Bestimmte Aufgabe ausführen möchten sollten Sie eine Prozedur aufrufen. Wenn Sie eine Schleife oder Prozedur verlassen wollen, dann sagen Sie das auch.
QB hat das Problem, das verschachtelte Schleifen nicht direkt verlassen werden können, da 'Exit ...' nur eine Schleife verlässt. Hier ist ein Fall, in dem nicht zwanghaft GOTO vermieden werden sollte. Spätestens, wenn Sie merken, das Sie einen dirty Hack verwenden, sollten Sie lieber zu einem 'GOTO' greifen:
FOR i = 0 TO n FOR j = 0 TO m ... IF bedingung THEN ' Der dirty Hack i = n + 1 EXIT FOR END IF ... NEXT NEXT
Wie gesagt stattdessen lieber:
FOR i = 0 TO n FOR j = 0 TO m ... IF bedingung THEN ' die GOTO-Alternative GOTO SinnvollerNameFuerDenAbbruch END IF ... NEXT NEXT SinnvollerNameFuerDenAbbruch:
Wenn Sie sich an die Regel eine Prozedur für eine Aufgabe halten, werden Sie aber selten in eine solche Situation kommen.
SUB SinnvollerNameFuerDieAufgabe (...) FOR i = 0 TO n FOR j = 0 TO m ... IF bedingung THEN ' ohne dirty Hack EXIT SUB END IF ... NEXT NEXT END SUB