4D v16.3

Projektmethoden

Home

 
4D v16.3
Projektmethoden

Projektmethoden  


 

 

Projektmethoden werden je nach Situation benannt. Sie sind im Gegensatz zu Formular- und Objektmethoden überall verfügbar. Sie sind nicht an spezifische Objekte in der Datenbank gebunden. Je nach Ausführung und Verwendung kann eine Projektmethode folgende Rolle haben:

  • Menümethode
  • Unterroutine und Funktion
  • Prozessmethode
  • Ereignisbezogene Methode
  • Fehlerbezogene Methode

Projektmethoden sind an keine vordefinierte Situation gebunden. Es bleibt Ihnen als Programmierer überlassen, die notwendigen Elemente zu bestimmen:

Eine Menümethode wird in einem eigenen Menü aufgerufen. Sie steuert den Ablauf Ihrer Anwendung und nimmt bei Bedarf eine bestimmte Richtung. Die Menümethode zeigt Formulare an, erstellt Berichte und verwaltet ganz allgemein Ihre Datenbank.

Eine Unterroutine ist eine Projektmethode, die als Diener fungiert. Sie führt die Aufgaben aus, die ihr von anderen Methoden aufgetragen werden. Eine Funktion ist eine Unterroutine, die der Methode, die sie aufruft, einen Wert zurückgibt.

Eine Prozessmethode wird aufgerufen, wenn ein Prozess startet. Der Prozess dauert nur solange, wie die Prozessmethode ausgeführt wird. Weitere Informationen zu Prozessen finden Sie im Kapitel Prozesse. Eine Menümethode, die einem Menübefehl mit der Eigenschaft Starte neuen Prozeß zugeordnet ist, ist gleichzeitig die Prozessmethode für den neu gestarteten Prozess.

Eine ereignisbezogene Methode läuft in einem eigenen Prozess, der nach Ereignissen sucht. Normalerweise verwaltet 4D die meisten Ereignisse automatisch für Sie. Beispielsweise bei der Dateneingabe nimmt 4D Tastaturkürzel und Klicks wahr, ruft die entsprechenden Objekt- und Formularmethoden auf, so dass Sie von diesen Methoden aus auf die Ereignisse entsprechend antworten können. Unter bestimmten Voraussetzungen möchten Sie jedoch Ereignisse direkt verwalten. Sie möchten bei länger andauernden Operationen (wie die Schleife For...End for zum Durchlaufen von Datensätzen) z.B. die Möglichkeit haben, die Operation zu unterbrechen, und zwar unter Windows mit der Tastenkombination Strg + Punkt, auf Macintosh Befehl + Punkt. Dafür verwenden Sie eine ereignisbezogene Methode. Weitere Informationen dazu finden Sie in der Beschreibung des Befehls ON EVENT CALL.

Eine fehlerbezogene Methode ist eine unterbrechende Projektmethode. Immer wenn ein Fehler oder eine Ausnahme auftreten, läuft diese Methode in dem Prozess ab, in welchem sie installiert ist. Weitere Informationen dazu finden Sie in der Beschreibung des Befehls ON ERR CALL.

Eine Menümethode wird in der Anwendungsumgebung aufgerufen, wenn Sie den dazugehörigen Menübefehl auswählen. Sie weisen die Methode dem Menübefehl im Methodeneditor zu. Dies ist einer der Hauptaspekte bei der eigenen Gestaltung von Datenbanken. Durch Einrichten eigener Menüs mit dazugehörigen Menümethoden, die bestimmte Aktionen ausführen, personalisieren Sie Ihre Datenbank. Weitere Informationen dazu finden Sie im Handbuch 4D Designmodus.

Mit eigenen Menübefehlen können eine oder mehrere Aktivitäten ausgelöst werden. Ein Menübefehl für die Eingabe von Datensätzen kann beispielsweise zwei Tasks ausführen: Das entsprechende Eingabeformular anzeigen und den Befehl ADD RECORD aufrufen, bis der Benutzer die Eingabe von Daten beendet.

Das automatische Ablaufen von mehreren Aktivitäten ist eine Leistungsstärke der Programmiersprache. Über eigene Menüs automatisieren Sie mehrere Tasks, die sonst manuell in der Anwendungsumgebung durchgeführt werden müssten. Benutzer der Datenbank werden so besser geführt, sie müssen sich keine Gedanken über die nächste Aktion machen.

Eine Projektmethode wird Teil der Programmiersprache für die Datenbank, in der Sie diese erstellt haben. Sie können die Projektmethode dann wie einen der 4D Befehle aufrufen. Eine so verwendete Projektmethode heißt Unterroutine.

Sie verwenden Unterroutinen, um:

  • Sich wiederholendes Programmieren zu reduzieren
  • Ihre Methoden klarer zu gliedern
  • Ihre Methoden schnellerzu ändern
  • Ihren Code modular aufzuteilen.

Wir gehen beispielsweise von einer Datenbank Kunden aus. Bei der individuellen Gestaltung stellen Sie fest, dass sich einige Vorgänge wiederholen, wie einen Kunden finden oder einen Datensatz ändern. Der Code dafür könnte folgendermaßen aussehen:

  ` Suche nach Kunde
 QUERY BY EXAMPLE([Customers])
  ` Wähle das Eingabeformular
 FORM SET INPUT([Customers];"Data Entry")
  ` Ändere den Kundendatensatz
 MODIFY RECORD([Customers])

Arbeiten Sie ohne Unterroutinen, müssen Sie den Code immer schreiben, wenn Sie einen Kundendatensatz ändern wollen. Passiert das in Ihrer Datenbank an zehn Stellen, müssen Sie den Code zehnmal schreiben. Mit Unterroutinen schreiben Sie den Code nur einmal, sie können dadurch Programmierzeilen einsparen.

Wir legen den oben beschriebenen Code in einer Methode mit Namen MODIFY CUSTOMER an. Soll diese Methode in einer anderen Methode ausgeführt werden, müssen Sie nur den Namen einsetzen. Wollen Sie beispielsweise einen Kundendatensatz ändern und dann den Datensatz drucken, schreiben Sie folgende Methode:

 MODIFY CUSTOMER
 PRINT SELECTION([Customers])

Ihre Methode vereinfacht sich entscheidend. Sie müssen nicht wissen, wie die Methode MODIFY CUSTOMER arbeitet, sondern nur was sie tut. Dies ist ein Vorteil von Unterroutinen: Ihre Methoden werden klarer. Sie erweitern sozusagen die 4D Programmiersprache.

Wollen Sie in dieser Beispieldatenbank die Methode zum Auffinden von Kunden ändern, müssen Sie nur eine und nicht zehn Methoden ändern. Ein weiterer Vorteil von Unterroutinen: Methoden sind schnell geändert.

Mit Unterroutinen bauen Sie Ihren Code modular auf. Das bedeutet, sie unterteilen Ihren Code in Module (Unterroutinen), die jeweil ein logisches Task ausführen. Betrachten Sie folgenden Code aus einer Datenbank für Kontoführung:

 FIND CLEARED CHECKS ` Finde alle bezahlten Schecks
 RECONCILE ACCOUNT ` Gleiche Konto aus
 PRINT CHECK BOOK REPORT ` Drucke Scheckbuch Bericht

Auch für jemanden, der die Datenbank nicht kennt, ist klar, was der Code ausführt. Er muss nicht jede Unterroutine prüfen, die evtl. aus vielen Zeilen besteht und komplexe Operationen ausführt. Wichtig ist, dass die Tasks ausgeführt werden.

Wir empfehlen, den Code, immer wenn möglich, in logische Tasks oder Module aufzuteilen.

Bei größeren Programmen müssen Sie in Ihren Methoden oft auch Daten übergeben. Dazu setzen Sie Parameter ein.

Eine Methode benötigt Parameter (oder Argumente) zum Ausführen der Tasks. Dieses Handbuch verwendet beide Begriffe. Parameter werden in den 4D Befehlen übergeben. In diesem Beispiel ist die Zeichenkette “Hello” ein Argument des Befehls ALERT:

 ALERT("Hello")

Auf dieselbe Weise werden auch Parameter in Methoden übergeben. Hier lässt die Methode DO SOMETHING drei Parameter zu:

 DO SOMETHING(WithThis;AndThat;ThisWay)

Parameter sind durch Strichpunkt voneinander getrennt (;).

In der Unterroutine (die aufgerufene Methode) wird der Wert jedes Parameters automatisch in durchnummerierte lokale Variablen kopiert: $1, $2, $3, etc.. Diese geben die Reihenfolge der Parameter an.

  //Code der Methode DO SOMETHING
  //Alle Parameter sind vom Typ Text
 C_TEXT($1;$2;$3)
 ALERT("I received "+$1+" and "+$2+" and also "+$3)
  //$1 enthält den Parameter WithThis
  //$2 enthält den Parameter AndThat
  //$3 enthält den Parameter ThisWay

Sie können die Parameter $1, $2... in der Unterroutine genauso wie jede andere lokale Variable verwenden. Jedoch lassen sich bei Befehlen, welche den Wert der als Parameter übergebenen Variablen verändern, z.B. Find in field, die Parameter $1, $2, etc. nicht direkt verwenden. Sie müssen sie zuerst in lokale Standardvariablen kopieren (z.B. $myvar.=$1).

Weiterführender Hinweis: 4D Projektmethoden akzeptieren eine variable Anzahl von Parametern gleichen Typs, beginnend von rechts. Zum Deklarieren dieser Parameter verwenden Sie eine Compiler Direktive, in der Sie {${N} als Parameter übergeben, wobei N den ersten Parameter angibt. Zum Beispiel gibt die Deklaration C_LONGINT(${5}) 4D und dem Compiler an, dass die Methode ab dem fünften Parameter eine variable Anzahl Parameter vom Typ Lange Ganzzahl empfangen kann. Mit der Funktion Count parameters haben Sie über eine For Schleife und die Parameter Indirektion Syntax Zugriff auf diese Parameter. Weitere Informationen dazu finden Sie im 2. Beispiel unter Count parameters.

Parameter werden je nach Typ als Kopie oder als Referenz übergeben:

  • Bei Übergabe als Kopie sind die lokalen Variablen/Parameter nicht die aktuellen Felder, Variablen oder Ausdrücke, übergeben von der aufrufenden Methode; sie enthalten nur die übergebenen Werte. Da ihre Reichweite lokal ist, wird ein in der Unterroutine geänderte Wert in der aufrufenden Methode nicht verändert.
  • Bei Übergabe als Referenz enthalten die lokalen Variablen/Parameter Referenzen auf die aktuellen Ausgangsfelder, -variablen oder -ausdrücke, übergeben von der aufrufenden Methode; Wird nun der Wert des lokalen Parameters geändert, ändert das auch den Ausgangswert.

Nachfolgende Tabelle zeigt, wie sich die verschiedenen Elementtypen übergeben lassen:

ParametertypÜbergeben alsKommentar
Feld, Variable oder Ausdruck eines skalaren Typs (Zahl, Text, Datum...)WertLässt sich durch einen Zeiger als Referenz übergeben, siehe unten
Feld, Variable oder Ausdruck vom Typ ObjektReferenzSiehe Beispiel unten
Variable oder Ausdruck vom Typ CollectionReferenz
Variable oder Ausdruck vom Typ ZeigerReferenzSiehe Zeiger in Methoden
ArrayLässt sich nicht direkt als Parameter übergebenLässt sich durch einen Zeiger als Referenz übergeben, siehe Arrays und Zeiger
TabelleLässt sich nicht direkt als Parameter übergebenLässt sich durch einen Zeiger als Referenz übergeben, siehe Zeiger

Bei Feldern, Variablen und Ausdrücken vom skalaren Typ werden als Parameter für Methoden nur Kopien der Werte übergeben.

Da $1, $2 lokale Variablen sind, sind sie nur innerhalb der Unterroutine verfügbar und werden am Ende der Unterroutine gelöscht. Von daher kann eine Unterroutine nicht den Wert der aktuellen Datenfelder oder Variablen ändern, die auf Methodenebene als Parameter übergeben werden. Beispiel:

  ` Ausschnitt aus dem Code der Methode MY METHOD
  ` ...
 DO SOMETHING([People]Last Name) ` [People]Last Name sei gleich "weber"
 ALERT([People]Last Name)
 
  ` Code der Methode DO SOMETHING
 $1:=Uppercase($1)
 ALERT($1)

Die von DO SOMETHING angezeigte Meldung liest “WEBER”, die von MY METHOD angezeigte Meldung liest “weber”. Die Methode hat den Wert des Parameters $1 lokal geändert, das verändert jedoch nicht den Wert des Datenfeldes [People]Last Name, der von der Methode MY METHOD als Parameter übergeben wurde.

Es gibt zwei Möglichkeiten, den Wert des Datenfeldes in der Methode DO SOMETHING zu ändern:

1. Sie übergeben in der Methode nicht das Datenfeld, sondern einen Zeiger darauf:

  ` Ausschnitt aus dem Code der Methode MY METHOD
  ` ...
 DO SOMETHING(->[People]Last Name) ` [People]Last Name sei gleich "weber"
 ALERT([People]Last Name)
 
  ` Code der Methode DO SOMETHING
 $1->:=Uppercase($1->)
 ALERT($1->)

Der Parameter ist hier nicht das Datenfeld selbst, sondern ein Zeiger darauf. Das von $1 referenzierte Objekt ($1->) ist das aktuelle Datenfeld. Wird nun das referenzierte Objekt geändert, geht das über die Reichweite der Unterroutine hinaus und wirkt sich auf das aktuelle Datenfeld aus. In diesem Beispiel lesen beide Meldedialoge “WEBER”.

Weitere Informationen dazu finden Sie im Abschnitt WA GET EXTERNAL LINKS FILTERS.

2. Sie können die Methode DO SOMETHING so umschreiben, dass sie nicht etwas ausführt, sondern einen Wert zurückgibt:

  ` Ausschnitt aus dem Code der Methode MY METHOD
  ` ...
 [People]Last Name:=DO SOMETHING([People]Last Name)
  ` [People]Last Name sei gleich "weber"
 ALERT([People]Last Name)
 
  ` Code der Methode DO SOMETHING
 $0:=Uppercase($1)
 ALERT($0)

Diese Technik heißt auch “eine Funktion verwenden”. Sie wird im nächsten Abschnitt beschrieben.

Bei Verwendung von Variablen, Ausdrücken oder Feldern vom Typ Objekt oder Collection als Parameter von Methoden werden Referenzen auf aktuelle Ausgangswerte übergeben. In diesem Fall enthält $1, $2... keine Werte sondern Referenzen. Wird der Wert von $1, $2... in der Unterroutine geändert, wirkt sich die Änderung überall aus, wo das Quellobjekt oder die Collection verwendet werden. Das ist das gleiche Prinzip wie für Zeiger, mit dem Unterschied, dass die Parameter $1, $2... in der Unterroutine nicht dereferenziert werden müssen.

Zum Beispiel:

  //Die Methode CreatePerson erstellt ein Objekt und sendet es als Parameter
 C_OBJECT($person)
 $person:=New object("Name";"Smith";"Age";40)
 ChangeAge($person)
 ALERT(String(OB get($person;"Age")))

  //Die Methode ChangeAge fügt 10 zum Attribut Age des empfangenen Objekts hinzu
 C_OBJECT($1)
 OB SET($1;"Age";OB Get($1;"Age")+10)
 ALERT(String(OB get($1;"Age")))

Bei Ausführen der Methode CreatePerson lesen beide Meldungsboxen "50", da beide Methoden dieselbe Referenz verwalten.

4D Server: Werden Parameter zwischen Methoden übergeben, die nicht auf demselben Rechner ausgeführt werden (z.B. die Option Execute on Server, siehe Eigenschaften für Projektmethoden), lassen sich Referenzen nicht verwenden. In diesen Fällen werden anstelle von Referenzen Kopien von Objekt und Collection Parametern gesendet.

Daten können auch von Methoden zurückgeben werden. Eine Methode, die einen Wert zurückgibt, heißt Funktion.

4D oder 4D Plug-in Befehle, die einen Wert zurückgeben, heißen ebenfalls Funktionen.

Folgende Programmierzeile verwendet die vordefinierte Funktion Length, sie gibt die Länge einer Zeichenkette zurück. Der von Length zurückgegebene Wert wird in eine Variable mit Namen MyLength gesetzt:

 MyLength:=Length("How did I get here?")

Jede Unterroutine kann einen Wert zurückgeben. Der zurückzugebende Wert wird in die lokale Variable $0 gesetzt.

Folgende Funktion mit Namen Uppercase4 gibt eine Zeichenkette mit den ersten vier Zeichen in Großbuchstaben zurück:

 $0:=Uppercase(Substring($1;1;4))+Substring($1;5)

Dieses Beispiel verwendet die Funktion Uppercase4:

 NewPhrase:=Uppercase4("This is good.")

Die Variable NewPhrase erhält “THIS is good.”

Das Ergebnis der Funktion $0 ist eine lokale Variable in der Unterroutine. Sie kann als solche in der Unterroutine verwendet werden. Im vorigen Beispiel DO SOMETHING wurde $0 zuerst der Wert von $1 zugewiesen, dann war sie Parameter für den Befehl ALERT. Sie können $0 in der Unterroutine genauso wie jede andere lokale Variable verwenden. 4D übergibt der aufgerufenen Methode den Wert von $0 (so als ob die Unterroutine endet).

Projektmethoden können sich auch selbst aufrufen, d.h. sie sind rekursiv. Beispiel:

  • Die Methode A ruft die Methode B auf, die A aufruft, so ruft A wieder B auf, usw..
  • Eine Methode kann sich selbst aufrufen.

Die 4D Programmiersprache unterstützt Rekursivität.

Hier ein Beispiel. Wir haben eine Tabelle [Friends and Relatives], die extrem vereinfacht, so aussieht:
- [Friends and Relatives]Name
- [Friends and Relatives]Children'Name

Wir gehen davon aus, dass die Werte der Datenfelder einmalig sind, d.h. es gibt nicht zwei Personen mit demselben Namen. Sie wollen für einen gegebenen Namen folgenden Satz erstellen: “Hans, mein Freund, der das Kind ist von Paul, der das Kind ist von Susi, die das Kind ist von Robert, der das Kind ist von Elisabeth, tut dies für sein Leben gern!”:

1. Sie können den Satz folgendermaßen anlegen:

 $vsName:=Request("Gib den Namen ein:";"Hans")
 If(OK=1)
    QUERY([Friends and Relatives];[Friends and Relatives]Name=$vsName)
    If(Records in selection([Friends and Relatives])>0)
       $vtTheWholeStory:="Mein Freund, "+$vsName
       Repeat
          QUERY([Friends and Relatives];[Friends and Relatives]Children'Name=$vsName)
          $vlQueryResult:=Records in selection([Friends and Relatives])
          If($vlQueryResult>0)
             $vtTheWholeStory:=$vtTheWholeStory+" der das Kind ist von
             "+[Friends and Relatives]Name
             $vsName:=[Friends and Relatives]Name
          End if
       Until($vlQueryResult=0)
       $vtTheWholeStory:=$vtTheWholeStory+", tut dies für sein Leben gern!"
       ALERT($vtTheWholeStory)
    End if
 End if

2. oder folgendermaßen:

 $vsName:=Request("Gib den Namen ein:";"Hans")
 If(OK=1)
    QUERY([Friends and Relatives];[Friends and Relatives]Name=$vsName)
    If(Records in selection([Friends and Relatives])>0)
       ALERT("Mein Freund, "+Genealogy of($vsName)+", tut dies für sein Leben gern!")
    End if
 End if

mit der rekursiven Methode Genealogy of:

  ` Projektmethode Genealogy of
  ` Genealogy of ( String ) -> Text
  ` Genealogy of ( Name ) -> Satzteil
 
 $0:=$1
 QUERY([Friends and Relatives];[Friends and Relatives]Children'Name=$1)
 If(Records in selection([Friends and Relatives])>0)
    $0:=$0+" der das Kind ist von "+Genealogy of([Friends and Relatives]Name)
 End if

Beachten Sie die Methode Genealogy of, die sich selbst aufruft.

Die erste Möglichkeit ist ein iterativer Algorithmus, die zweite ein rekursiver Algorithmus.

Hinweis: Sie können bei Programmierungen wie im oben aufgeführten Beispiel sowohl iterative als auch rekursive Methoden schreiben. Rekursivität macht die Programmierung im allgemeinen präziser, leichter zu lesen und zu warten, sie ist jedoch nicht zwingend.

Einige typische Verwendungen für Rekursivität in 4D sind:

  • Datensätze in Tabellen bearbeiten, die wie im obigen Beispiel miteinander verknüpft sind.
  • Dokumente und Ordner auf Ihrer Festplatte mit den Befehlen FOLDER LIST und DOCUMENT LIST durchlaufen. Ein Ordner kann Ordner und Dokumente enthalten, die Unterordner selbst können Ordner und Dokumente enthalten, usw..

Wichtig: Rekursive Abfragen sollten immer an einem bestimmten Punkt enden. Im Beispiel ruft sich die Methode Genealogy of nicht mehr selbst auf, wenn die Suche keinen Datensatz zurückgibt. Ohne Abfragen dieser Bedingung würde sich die Methode endlos aufrufen; 4D gibt dann evtl. eine Fehlermeldung “Speicher voll” zurück, da es keinen Platze mehr hat zum Stapeln der Aufrufe (so wie bei Parametern und lokalen Variablen in den Methoden).



Siehe auch 

Ablaufsteuerung
Datenbankmethoden
Methoden

 
EIGENSCHAFTEN 

Produkt: 4D
Thema: Grundbegriffe

 
GESCHICHTE 

 
ARTIKELVERWENDUNG

4D Programmiersprache ( 4D v16)
4D Programmiersprache ( 4D v16.1)
4D Programmiersprache ( 4D v16.2)
4D Programmiersprache ( 4D v16.3)