version 6.0
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 Introduction aux 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 APPELER SUR EVENEMENT.
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 APPELER SUR ERREUR.
Méthodes de menu
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 menus.
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 AJOUTER ENREGISTREMENT 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.
Sous-routines
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 CHERCHER PAR EXEMPLE([Clients]) ` Sélection du formulaire entrée FORMULAIRE ENTREE([Clients];"Saisie de données") ` Modification de l'enregistrement du client MODIFIER ENREGISTREMENT([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 IMPRIMER 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.
Passer des paramètres aux méthodes
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 ALERTE :
ALERTE("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.
Ces variables/paramètres locaux ne sont pas réellement les champs, variables ou expressions passées à la méthode appelante : elles contiennent simplement leurs valeurs.
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.
Puisque ces variables sont 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" ALERTE([Personnes]Nom) ` Voici le code de la méthode FAIRE QUELQUE CHOSE $1:=Majusc($1) ALERTE($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" ALERTE([Personnes]Nom) ` Voici le code de la méthode FAIRE QUELQUE CHOSE $1->:=Majusc($1->) ALERTE($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" ALERTE([Personnes]Nom) ` Voici le code de la méthode FAIRE QUELQUE CHOSE $0:=$1 ALERTE($0)
Une sous-routine retournant une valeur est appelée une fonction. Ce point est traité dans les paragraphes suivants.
Note de programmation avancée : Les paramètres à l'intérieur de la sous-routine sont accessibles par l'intermédiaire des variables locales $1, $2... De plus, des paramètres peuvent être optionnels et être référencés à l'aide de la syntaxe ${...}. Pour plus d'informations sur ce point, reportez-vous à la description de la commande Nombre de parametres.
Les fonctions, méthodes projet retournant une valeur
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, Longueur, qui retourne la longueur d'une chaîne. La valeur retournée par Longueur est placée dans une variable appelée MaLongueur :
MaLongueur:=Longueur("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:=Majusc(Sous chaine($1; 1; 4))+Sous chaine($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 ALERTE. 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.
Méthode projet récursives
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:=Demander("Saisissez le nom :";"Pierre") Si (OK=1) CHERCHER([Amis et parents];[Amis et parents]Nom=$vsNom) Si (Enregistrements trouves([Amis et parents])>0) $vtHistoireComplète:="Un de mes amis, "+$vsNom Repeter CHERCHER([Amis et parents];[Amis et parents]Enfant'Nom=$vsNom) $vlResultRecherche:=Enregistrements trouves([Amis et parents]) Si ($vlResultRecherche>0) $vtHistoireComplète:=$vtHistoireComplète+" qui est le rejeton de "+[Amis et parents]Nom $vsNom:=[Amis et parents]Nom Fin de si Jusque ($vlResultRecherche=0) $vtHistoireComplète:=$vtHistoireComplète+", fait cela pour gagner sa vie !" ALERTE($vtHistoireComplète) Fin de si Fin de si
2. Vous pouvez également procéder ainsi :
$vsNom:=Demander("Saisissez le nom :";"Pierre") Si (OK=1) CHERCHER([Amis et parents];[Amis et parents]Nom=$vsNom) Si (Enregistrements trouves([Amis et parents])>0) ALERTE("Un de mes amis, "+Généalogie de ($vsNom)+", fait cela pour gagner sa vie !") Fin de si Fin de si
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 CHERCHER([Amis et parents];[Amis et parents]Enfant'Nom=$1) Si (Enregistrements trouves([Amis et parents])>0) $0:=$0+" qui est le rejeton de "+Généalogie de ([Amis et parents]Nom) Fin de si
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 LISTE DES DOSSIERS et LISTE DES DOCUMENTS. 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).
Référence
Conditions et boucles, Méthodes, Présentation des méthodes base.