Dictionnaire de données et de traitements
Dans le cadre de la programmation classique, quand deux programmes travaillent ensemble, les informaticiens ont défini au préalable le schéma de communication entre eux au moyen d'un protocole. Tout ce qu'un programme peut potentiellement utiliser ou accéder de l'autre programme est défini au moment de la conception de ceux-ci. Si, au cours du cycle de vie du programme, le premier programme doit accéder à de nouvelles données ou exécuter de nouveaux traitements, son code doit être revu.
En Up ! 5GL, les programmes ont une architecture à objets dynamique. Ils sont fondés sur Up ! Object Management System et ils sont constitués majoritairement de bibliothèques dynamiques changeables en cours d'exécution. De plus, les objets sont répartis sur tout le réseau de l'entreprise sans que leur localisation soit définie à la conception du programme. La localisation est à la charge de Up ! Object Request Broker.
De ce fait, au cours du cycle de vie d'un programme, de nouveaux objets peuvent être créés pour lesquels leur type n'était pas forcément défini au moment de la conception du programme. L'idée est de permettre néanmoins à ce programme d'utiliser les nouvelles données et les nouveaux traitements sans qu'il y ait lieu de revoir son code, voire même sans qu'il y ait lieu de l'arrêter. En effet, un programme serveur devant être toujours disponible, il n'est pas concevable de devoir l'arrêter parce qu'un nouveau type d'objet a été ajouté au modèle d'informations de l'entreprise.
Usage dynamique d'une donnée ou d'un traitement
L'instruction ImporterModule permet d'importer les définitions d'un module pour qu'un programme puisse utiliser les données ou les traitements de celui-ci. Up ! Compiler connaît à la compilation du programme la localisation des données et des traitements dans le code du module importé du fait de son interface. Dans ce cas, l'usage des données et des traitements est donc statique.
Quand le programme charge dynamiquement un module ou que le programme parcourt l'annuaire global, il peut être amené à employer des données et des traitements pour lesquels leur définitions étaient inconnues à Up ! Compiler au moment de la compilation. Pour connaître ces nouvelles définitions, le programme effeuille le dictionnaire des données et des traitements. Une fois les définitions interprétées, il peut alors utiliser ces données et ces traitements dynamiquement i.e sans qu'il y ait du code spécifique pour ces données ou ces traitements.
Par exemple, un programme trouve dans un annuaire un objet de type Document, type dont la définition est inconnue au moment de sa conception. Il interroge le dictionnaire de données pour connaître les propriétés de cet objet et le programme peut afficher ainsi à l'utilisateur NomDocument, Auteur, DateDernierEnregistrement représentant respectivement le nom du document, son auteur et sa date de dernier enregistrement. En interrogeant le dictionnaire de traitements pour connaître les méthodes applicables à cet objet, le programme peut proposer la méthode Visualiser et Imprimer respectivement pour visualiser et imprimer le document. Le dictionnaire spécifie que la méthode Imprimer nécessite un paramètre qui est le nom de l'imprimante.
Dictionnaire de données et de traitements
Le dictionnaire de données mémorise pour chaque module les données qui y sont disponibles. Le dictionnaire de traitements mémorise pour chaque module les traitements qui y sont disponibles. Ces dictionnaires sont pour partie conservés dans l'entrepôt Systeme et pour partie calculés dynamiquement à chaque interrogation. Ils sont basés sur cinq entités :
- Le type Module modélisant un module du programme.
- Le type Type modélisant un type de données.
- Le type Objet modélisant un objet.
- Le type Appel modélisant les appels de procédure, de fonction ou de méthode.
- Le type Entrepot modélisant les entrepôts de stockage des objets.
Un type est rattaché au module dans lequel il a été défini par la propriété ModuleOrigine. Un appel est rattaché au module dans lequel il a été défini par la propriété ModuleOrigine.
Les objets sont tous rattachés à leur type de définition par la propriété EstInstanceDe. Il est possible d'énumérer tous les objets d'un type au moyen de la méthode EnumererObjets du type Type. En appliquant cette méthode au type Module, cela permet d'énumérer tous les modules constituant le programme. Voici comment interroger le dictionnaire de données et de traitements :
- La méthode EnumererEnumeres du type Module permet de retrouver tous les énumérés publics d'un module.
La méthode EnumereValeursEnumeres du type Module permet de retrouver toutes les valeurs d'un énuméré d'un module.
- La méthode EnumererEntrepots du type Module permet de retrouver toutes les entrepôts publics d'un module.
La méthode EnumererObjets du type Type appliquée au type Entrepot permet de retrouver tous les entrepôts.
- La méthode EnumererTypes du type Module permet de retrouver tous les types publics d'un module.
La méthode EnumererObjets du type Type permet de retrouver tous les types quel que soit le module.
- La méthode EnumererVariables du type Module permet de retrouver toutes les variables globales publiques ou en lecture publique d'un module.
- La méthode EnumererExceptions du type Module permet de retrouver toutes les exceptions publiques d'un module.
La méthode EnumererObjets du type Exception permet de retrouver toutes les exceptions quel que soit le module.
- La méthode EnumererObjets du type FileDAttente permet de retrouver toutes les files d'attente quel que soit le module.
- La méthode EnumererProprietes du type Objet permet de retrouver toutes les propriétés publiques ou en lecture publique d'un objet.
Si le type de cet objet supporte les propriétés dynamiques, elles sont également énumérées.
- La méthode EnumererMethodes du type Type permet de retrouver toutes les méthodes publiques d'un type.
- La méthode EnumererAppels du type Module permet de retrouver tous les appels publics d'un module sauf les méthodes.
- La méthode EnumererParametres du type Appel permet de retrouver tous les paramètres d'un appel.
Usage dynamique des données
Pour employer statiquement une variable, il suffit d'employer son nom dans le programme. La lecture dynamique de la valeur d'une variable s'effectue au moyen de la méthode LireVariable du type Module. L'écriture dynamique de la valeur d'une variable s'effectue au moyen de la méthode EcrireVariable du type Module. L'incrémentation ou la décrémentation dynamique de la valeur d'une variable s'effectue au moyen de la méthode IncrementerDecrementerVariable du type Module.
Pour employer statiquement une propriété d'un objet, il suffit d'employer son nom dans le programme précédé de l'opérateur . . La lecture dynamique de la valeur d'une propriété s'effectue au moyen de la méthode LirePropriete du type Objet. L'écriture dynamique de la valeur d'une propriété s'effectue au moyen de la méthode EcrirePropriete du type Objet. L'incrémentation ou la décrémentation dynamique de la valeur d'une propriété s'effectue au moyen de la méthode IncrementerDecrementerPropriete du type Objet.
Usage dynamique des traitements
Pour employer statiquement une procédure ou une fonction, il suffit d'employer son nom dans le programme. L'exécution dynamique d'une procédure s'effectue au moyen de la méthode ExecuterProcedure du type Appel. L'exécution dynamique d'une fonction s'effectue au moyen de la méthode ExecuterFonction du type Appel.
Pour employer statiquement une méthode procédurale ou fonctionnelle, il suffit d'employer son nom dans le programme précédé de l'opérateur . . L'exécution dynamique d'une méthode procédurale s'effectue au moyen de la méthode ExecuterProcedure du type Appel. L'exécution dynamique d'une méthode fonctionnelle s'effectue au moyen de la méthode ExecuterFonction du type Appel.