4D v16.3

Méthodes projet

Accueil

 
4D v16.3
Méthodes projet

Méthodes projet  


 

 

Les méthodes projet, comme leur nom l’indique, s’appliquent à la totalité de votre projet, c’est-à-dire votre base de données. Alors que les méthodes formulaire ou les méthodes objet par exemple sont associées à des formulaires ou des objets, une méthode projet est disponible partout — elle n'est associée à aucun élément particulier de la base. Une méthode projet peut tenir les rôles suivants, en fonction de la manière dont elle est exécutée et utilisée :

  • Méthode de menu
  • Sous-routine et fonction
  • Méthode de gestion de process
  • Méthode de gestion d’événements
  • Méthode de gestion d’erreurs

Ces appellations ne qualifient pas la nature des méthodes (ce qu'elles sont), mais leur fonction (ce qu'elles font).

Une méthode de menu est une méthode projet appelée depuis une commande de menu personnalisé. Elle se comporte comme un agent de police chargé de la circulation, dirigeant les flux de votre application. Les méthodes de menu contrôlent, aiguillent lorsque c’est nécessaire, affichent les formulaires, génèrent des états ou encore gèrent votre base.

Le deuxième type de méthode projet peut être considéré comme une méthode asservie — d’autres méthodes lui demandent d’effectuer des tâches. Ce type de méthode est appelé sous-routine. Une sous-routine qui retourne une valeur est appelée une fonction.

Une méthode de gestion de process est une méthode projet appelée lorsqu’un process est démarré. Le process existera tant que la méthode sera en cours d'exécution. Pour plus d'informations sur les process, reportez-vous à la section Process. A noter qu'une méthode de menu associée à une commande de menu pour laquelle la propriété Démarrer un nouveau process est sélectionnée, est aussi la méthode de gestion de process pour le process créé.

Une méthode de gestion d’événements est une méthode dédiée à la gestion des événements, qui s'exécute dans un process différent de celui de la méthode de gestion des process. Généralement, pour la gestion des événements, vous pouvez laisser 4D faire le gros du travail. Par exemple, lors de la saisie de données, 4D détecte les clics souris et les touches enfoncées, puis appelle les méthodes objet et formulaire correspondantes, vous permettant ainsi de prévoir dans ces méthodes les traitements appropriés aux événements.
Dans d'autres circonstances, vous devez gérer directement les événements. Si, par exemple, vous exécutez une opération de longue durée (telle qu'une Boucle...Fin de boucle appliquée à chaque enregistrement), vous souhaitez pouvoir interrompre l'opération en tapant la touche Esc. Dans ce cas, une méthode de gestion d'événements est parfaitement adaptée. Pour plus d'informations, reportez-vous à la description de la commande ON EVENT CALL.

Une méthode de gestion d’erreurs est une méthode projet d'interruption. Elle s'exécute à l'intérieur du process dans lequel elle a été installée à chaque fois qu'une erreur se produit. Pour plus d'informations, reportez-vous à la description de la commande ON ERR CALL.

Une méthode de menu est appelée en mode Application lorsque la commande de menu personnalisé à laquelle elle est associée est sélectionnée. Vous assignez la méthode à la commande de menu dans l’éditeur de menus de 4D. Lorsque l’utilisateur sélectionne la commande de menu, la méthode est exécutée. Ce fonctionnement est l’un des principaux aspects de la personnalisation d’une base de données. C’est en créant des menus qui appellent des méthodes de menu que vous personnalisez votre base. Reportez-vous au manuel Mode Développement de 4D pour plus d’informations sur l’éditeur de menu.

Les commandes de menus personnalisés peuvent déclencher une ou plusieurs actions. Par exemple, une commande de menu de saisie d’enregistrements peut appeler une méthode effectuant deux actions : afficher le formulaire entrée approprié et appeler la commande ADD RECORD jusqu’à ce que l’utilisateur annule la saisie de nouveaux enregistrements.

L’automatisation de séquences d’actions est une possibilité très puissante du langage de programmation de 4D. A l’aide des menus personnalisés, vous pouvez automatiser des séquences de tâches, vous permettez aux utilisateurs de naviguer plus facilement dans votre base.

Lorsque vous avez écrit une méthode projet,  elle devient partie intégrante du langage de la base dans laquelle elle a été créée. Vous pouvez alors l'appeler de la même manière que vous appelez les commandes intégrées de 4D. Une méthode projet utilisée de cette manière est appelée une sous-routine.

L'utilisation de sous-routines procure les avantages suivants :

  • Réduction du code répétitif,
  • Clarification des méthodes,
  • Modification plus facile des méthodes,
  • Création de code modulaire.

Imaginons par exemple que vous travaillez avec une base de clients. A mesure que vous construisez la base, vous vous apercevez que vous répétez souvent certaines tâches, telles que la recherche d’un client et la modification de son enregistrement. Le code nécessaire à l’accomplissement de cette opération pourrait être :

  ` Recherche d'un client
 QUERY BY EXAMPLE([Clients])
  ` Sélection du formulaire entrée
 FORM SET INPUT([Clients];"Saisie de données")
  ` Modification de l'enregistrement du client
 MODIFY RECORD([Clients])

Si vous n’utilisez pas de sous-routines, vous devrez écrire ce code à chaque fois que vous voudrez modifier l’enregistrement d’un client. Si cette opération peut être réalisée dans dix endroits différents de votre base, vous devrez la réécrire dix fois. Grâce aux sous-routines, vous ne l’écrirez qu’une seule fois en tout. C’est le premier avantage des sous-routines : réduire la quantité de code à écrire.

Si le code ci-dessus était une méthode projet appelée MODIFIER CLIENT, vous l’exécuteriez simplement en inscrivant son nom dans une autre méthode. Par exemple, pour modifier l’enregistrement d’un client puis l’imprimer, vous n’auriez qu’à écrire :

 MODIFIER CLIENT
 PRINT SELECTION([Clients])

Cette possibilité simplifie énormément vos méthodes. Dans l’exemple ci-dessus, il n’est pas nécessaire de savoir comment fonctionne la méthode MODIFIER CLIENT, mais uniquement ce qu’elle fait. C’est le deuxième avantage que vous pouvez tirer de l’utilisation de sous-routines : la clarification de votre code. Ainsi, ces méthodes deviennent en quelque sorte des extensions du langage de 4D.

Si vous devez modifier votre mode de recherche des clients, comme dans notre exemple, il vous suffit de modifier une seule méthode, et non dix. C’est un autre avantage des sous-routines : faciliter les modifications de votre code.

Avec les sous-routines, vous rendez votre code modulaire. Cela signifie simplement que vous dissociez votre code en modules (sous-routines), chacun d’entre eux effectuant une tâche logique. Examinez le code suivant, tiré d’une base de gestion de comptes chèques :

 CHERCHER CHEQUES EMIS ` Rechercher les chèques émis
 RAPPROCHER COMPTE ` Rapprocher le compte
 IMPRIMER RELEVE ` Imprimer un relevé

Même pour quelqu’un qui ne connaît pas la base, le code est clair. Il n’est pas nécessaire d’examiner chaque sous-routine. Elles peuvent contenir de nombreuses lignes d’instructions et effectuer des opérations complexes, mais l’important est ce qu’elles font.

Nous vous conseillons de découper votre code en tâches logiques, ou modules, à chaque fois que c’est possible.

Vous aurez souvent besoin de fournir des valeurs à vos méthodes. Vous pouvez facilement effectuer cette opération grâce aux paramètres.

Les paramètres (ou arguments) sont des données dont les méthodes ont besoin pour s’exécuter — le terme "paramètres" ou "arguments" est utilisé indifféremment dans ce manuel. Des paramètres sont également passés aux commandes intégrées de 4D. Dans l’exemple ci-dessous, la chaîne “Bonjour” est un paramètre de la commande ALERT :

 ALERT("Bonjour")

Les paramètres sont passés de la même manière aux méthodes. Par exemple, si la méthode FAIRE QUELQUE CHOSE accepte trois paramètres, l'appel à cette méthode pourrait être de la forme suivante :

 FAIRE QUELQUE CHOSE(AvecCeci;EtCela;CommeCeci)

Les paramètres sont séparés par des points-virgules (;).

Dans la sous-routine (la méthode appelée), la valeur de chaque paramètre est automatiquement copiée séquentiellement dans des variables locales numérotées : $1, $2, $3, etc. La numérotation des variables locales représente l’ordre des paramètres.

  //Code de la méthode FAIRE QUELQUE CHOSE
  //Supposons que tous les paramètres sont de type texte
 C_TEXT($1;$2;$3)
 ALERT("J'ai reçu "+$1+" et "+$2+" et aussi "+$3)
  //$1 contient le paramètre AvecCeci
  //$2 contient le paramètre EtCela
  //$3 contient le paramètre CommeCeci

A l'intérieur de la sous-routine, vous pouvez utiliser les paramètres $1, $2... de la même manière que vous utilisez les autres variables locales. Toutefois, dans le cas où vous utilisez des commandes qui modifient la valeur de la variable passée en paramètre (par exemple Find in field), les paramètres $1, $2... ne peuvent pas être utilisés directement. Vous devez d'abord les recopier dans des variables locales standard (par exemple $mavar:=$1).

Note de programmation avancée : Les méthodes projet de 4D acceptent un nombre variable de paramètres du même type, à la condition que ce soient les derniers paramètres de la méthode. Pour déclarer ces paramètres, il vous suffit d'utiliser une directive de compilation à laquelle vous passez ${N}) comme paramètre, où N désigne le premier paramètre de la suite. Par exemple, la déclaration C_LONGINT(${5}) indique à 4D et au compilateur qu'à partir du cinquième paramètre la méthode peut recevoir un nombre variable de paramètres de type entier long. Grâce à la commande Count parameters, vous pouvez accéder à ces paramètres au sein d'une boucle de type Boucle...Fin de boucle via la syntaxe d'indirection de paramètres (${...}). Pour plus d'informations sur ce point, reportez-vous à l'exemple 2 de la commande Count parameters.

En fonction de leur type, les paramètres sont passés par copie ou par référence :

  • Lorsqu'un paramètre est passé par copie, les variables/paramètres locaux ne sont pas réellement les champs, variables ou expressions passés à la méthode appelante : elles contiennent simplement leurs valeurs. Puisque sa portée est locale, si la valeur du paramètre est modifiée dans la sous-routine, cela ne change pas sa valeur dans la méthode appelante.
  • Lorsqu'un paramètre est passé par référence, les variables/paramètres locaux contiennent uniquement des références pointant sur les véritables champs, variables ou expressions passés à la méthode appelante. La modification de la valeur du paramètre local sera répercutée sur la valeur source.

Le tableau suivant indique comment les différents types d'éléments peuvent être passés :

Type de paramètreMode de passageCommentaire
Champ, variable ou expression de type scalaire (numérique, texte, date...)par valeurPeut être passé par référence à l'aide d'un pointeur, voir ci-dessous
Champ, variable ou expression de type Objetpar référenceVoir exemple ci-dessous
Variable ou expression de type Collectionpar référence
Variable ou expression de type Pointeurpar référenceVoir Passer des pointeurs aux méthodes
TableauNe peut pas être passé directement en paramètrePeut être passé par référence à l'aide d'un pointeur, voir Tableaux et pointeurs
TableNe peut pas être passée directement en paramètrePeut être passée par référence à l'aide d'un pointeur, voir Pointeurs

Lorsque vous utilisez des champs, variables ou expressions de type scalaire en tant que paramètres de méthodes projets, seules des copies des valeurs sont passées. 

Puisque $1, $2... sont des variables locales, elles ne sont définies qu’à l’intérieur de la sous-routine et sont effacées à la fin de son exécution. Pour cette raison, une sous-routine ne peut pas modifier, au niveau de la méthode appelante, la valeur réelle des champs ou des variables passé(e)s en paramètre. Par exemple :

  ` Voici une partie de la méthode MA METHODE
  ` ...
 FAIRE QUELQUE CHOSE([Personnes]Nom) ` Admettons que [Personnes]Nom est égal à "william"
 ALERT([Personnes]Nom)
 
  ` Voici le code de la méthode FAIRE QUELQUE CHOSE
 $1:=Uppercase($1)
 ALERT($1)

La boîte de dialogue d'alerte affichée par FAIRE QUELQUE CHOSE contiendra "WILLIAM" et celle affichée par MA METHODE contiendra "william". La méthode a modifié localement la valeur du paramètre $1, mais cela n'affecte pas la valeur du champ [Personnes]Nom passé en paramètre par la méthode MA METHODE.

Si vous voulez réellement que la méthode FAIRE QUELQUE CHOSE modifie la valeur du champ, deux solutions s'offrent à vous :

1. Plutôt que de passer le champ à la méthode, vous lui passez un pointeur :

  ` Voici une partie de la méthode MA METHODE
  ` ...
 FAIRE QUELQUE CHOSE(->[Personnes]Nom) ` Admettons que [Personnes]Nom est égal à "william"
 ALERT([Personnes]Nom)
 
  ` Voici le code de la méthode FAIRE QUELQUE CHOSE
 $1->:=Uppercase($1->)
 ALERT($1->)

Ici, le paramètre n'est pas le champ lui-même, mais un pointeur vers le champ. Ainsi, à l'intérieur de la méthode FAIRE QUELQUE CHOSE, $1 ne contient plus la valeur du champ mais un pointeur vers le champ. L'objet référencé par $1 ($1-> dans le code ci-dessus) est le champ lui-même. Par conséquent, la modification de l'objet référencé dépasse les limites de la sous-routine et le champ lui-même est affecté. Dans cet exemple, les deux boîtes de dialogue d'alerte afficheront "WILLIAM".

Pour plus d'informations sur les pointeurs, reportez-vous à la section Pointeurs.

2. Plutôt que la méthode FAIRE QUELQUE CHOSE “fasse quelque chose”, vous pouvez la réécrire de manière à ce qu'elle retourne une valeur :

  ` Voici une partie de la méthode MA METHODE
  ` ...
 [Personnes]Nom:=FAIRE QUELQUE CHOSE([Personnes]Nom) ` Admettons que [Personnes]Nom est égal à "william"
 ALERT([Personnes]Nom)
 
  ` Voici le code de la méthode FAIRE QUELQUE CHOSE
 $0:=Uppercase($1)
 ALERT($0)

Une sous-routine retournant une valeur est appelée une fonction. Ce point est traité dans les paragraphes suivants.

Lorsque vous utilisez des variables, expressions ou champs de type objet ou collection en tant que paramètres de méthodes projet, ce sont des références vers les données sources qui sont passées. Dans ce cas, $1, $2... ne contiennent pas les valeurs mais des références. Toute modification de la valeur des paramètres $1, $2... à l'intérieur de la sous-routine sera propagée partout où l'objet ou la collection source est utilisée. C'est le même principe que pour les pointeurs, excepté le fait que les paramètres $1, $2... n'ont pas besoin d'être déréférencés à l'intérieur de la sous-routine.

Par exemple :

  //La méthode CreatePerson crée un objet et l'envoie en tant que paramètre
 C_OBJECT($person)
 $person:=New object("Name";"Smith";"Age";40)
 ChangeAge($person)
 ALERT(String(OB Lire($person;"Age")))

  //La méthode ChangeAge ajoute 10 à l'attribut Age de l'objet reçu
 C_OBJECT($1)
 OB SET($1;"Age";OB Get($1;"Age")+10)
 ALERT(String(OB Lire($1;"Age")))

Si vous exécutez la méthode CreatePerson, les deux messages d'alerte contiendront "50" car la même référence est traitée par les deux méthodes.

4D Server : Lorsque des paramètres sont passés entre des méthodes qui ne sont pas exécutées sur la même machine (lors de l'utilisation de l'option Exécuter sur serveur par exemple, voir Propriétés des méthodes projet), il n'est pas possible d'utiliser des références. Dans ce cas, ce sont des copies des paramètres objet ou collection qui sont envoyées au lieu de références.

Les méthodes peuvent retourner des valeurs. Une méthode qui retourne une valeur est appelée une fonction.

Les commandes de 4D ou de plug-ins qui retournent une valeur sont également appelées fonctions.

Par exemple, la ligne d’instruction suivante utilise une fonction intégrée, Length, qui retourne la longueur d’une chaîne. La valeur retournée par Length est placée dans une variable appelée MaLongueur :

 MaLongueur:=Length("Comment suis-je arrivé là ?")

Toute sous-routine peut retourner une valeur. La valeur à retourner est placée dans la variable locale $0.

Par exemple, la fonction suivante, appelée Majuscules4, retourne une chaîne dont les quatre premiers caractères ont été passés en majuscules :

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

Voici un exemple qui utilise la fonction Majuscules4 :

 NouvellePhrase:=Majuscules4("Bien joué.")

Dans ce cas, la variable NouvellePhrase prend la valeur “BIEN joué.”

Le retour de fonction, $0, est une variable locale à la sous-routine. Elle peut être utilisée en tant que telle à l'intérieur de la sous-routine. Par exemple, dans le cas de la méthode FAIRE QUELQUE CHOSE utilisée précédemment, $0 recevait d'abord la valeur de $1, puis était utilisée en tant que paramètre de la commande ALERT. Dans une sous-méthode, vous pouvez utiliser $0 comme n'importe quelle autre variable locale. C'est 4D qui retourne sa valeur finale (sa valeur courante au moment où la sous-routine se termine) à la méthode appelée.

Des méthodes projet peuvent s'appeler les unes les autres, et en particulier :

  • Une méthode A peut appeler une méthode B, qui appelle A, donc A appelle B de nouveau, etc.
  • Une méthode peut s'appeler elle-même.

Cela s'appelle la récursivité. Le langage de 4D supporte pleinement la récursivité.

Examinons l'exemple suivant : vous disposez d'une table [Amis et relations] composée de l'ensemble de champs suivant (très simplifié) :
- [Amis et parents]Nom
- [Amis et parents]Enfant'Nom

Pour cet exemple, nous supposons que les valeurs des champs sont uniques (il n'existe pas deux personnes avec le même nom). A partir d'un nom, vous voulez écrire la phrase “Un de mes amis, Pierre, qui est le rejeton de Paul qui est le rejeton de Martine qui est le rejeton de Robert qui est le rejeton de Gertrude, fait cela pour gagner sa vie !” :

1. Vous pouvez procéder de la manière suivante :

 $vsNom:=Request("Saisissez le nom :";"Pierre")
 If(OK=1)
    QUERY([Amis et parents];[Amis et parents]Nom=$vsNom)
    If(Records in selection([Amis et parents])>0)
       $vtHistoireComplète:="Un de mes amis, "+$vsNom
       Repeat
          QUERY([Amis et parents];[Amis et parents]Enfant'Nom=$vsNom)
          $vlResultRecherche:=Records in selection([Amis et parents])
          If($vlResultRecherche>0)
             $vtHistoireComplète:=$vtHistoireComplète+" qui est le rejeton de "+[Amis et parents]Nom
             $vsNom:=[Amis et parents]Nom
          End if
       Until($vlResultRecherche=0)
       $vtHistoireComplète:=$vtHistoireComplète+", fait cela pour gagner sa vie !"
       ALERT($vtHistoireComplète)
    End if
 End if

2. Vous pouvez également procéder ainsi :

 $vsNom:=Request("Saisissez le nom :";"Pierre")
 If(OK=1)
    QUERY([Amis et parents];[Amis et parents]Nom=$vsNom)
    If(Records in selection([Amis et parents])>0)
       ALERT("Un de mes amis, "+Généalogie de($vsNom)+", fait cela pour gagner sa vie !")
    End if
 End if

en utilisant la fonction récursive Généalogie de suivante :

  ` Méthode projet Généalogie de
  ` Généalogie de ( Chaîne ) -> Texte
  ` Généalogie de ( Nom ) -> Partie de la phrase
 
 $0:=$1
 QUERY([Amis et parents];[Amis et parents]Enfant'Nom=$1)
 If(Records in selection([Amis et parents])>0)
    $0:=$0+" qui est le rejeton de "+Généalogie de([Amis et parents]Nom)
 End if

Vous notez que la méthode Généalogie de s'appelle elle-même.

La première manière de procéder utilise un algorithme itératif. La seconde manière utilise un algorithme récursif.

Lorsque vous implémentez du code pour traiter des cas comme celui décrit ci-dessus, vous aurez toujours le choix entre écrire des méthodes utilisant des algorithmes itératifs ou récursifs. Généralement, la récursivité permet d'écrire du code plus concis, lisible et plus facilement modifiable, mais utiliser la récursivité n'est absolument pas obligatoire.

Dans 4D, la récursivité est typiquement utilisée pour :

  • Traiter les enregistrements de tables liées les unes aux autres de la même manière que décrit dans l'exemple ci-dessus.
  • Naviguer parmi les documents et les dossiers de votre disque à l'aide des commandes FOLDER LIST et DOCUMENT LIST. Un dossier peut contenir des dossiers et des documents, les sous-dossiers peuvent eux-mêmes contenir des dossiers et des documents, etc.

Important : Les appels récursifs doivent toujours se terminer à un moment donné. Dans l'exemple ci-dessus, la méthode Généalogie de cesse de s'appeler elle-même lorsque la recherche ne trouve plus d'enregistrement. Sans ce test conditionnel, la méthode s'appellerait indéfiniment et 4D pourrait au bout d'un certain temps retourner l'erreur “La pile est pleine” car le programme n'aurait plus assez de place pour "empiler" les appels (ainsi que les paramètres et les variables locales utilisés dans la méthode).



Voir aussi  

Conditions et boucles
Méthodes
Présentation des méthodes base

 
PROPRIÉTÉS 

Produit : 4D
Thème : Présentation du langage

 
HISTORIQUE 

 
UTILISATION DE L'ARTICLE

4D - Langage ( 4D v16)
4D - Langage ( 4D v16.1)
4D - Langage ( 4D v16.2)
4D - Langage ( 4D v16.3)