Les avantages potentiels sont nombreux, et un générateur de code peut désormais faire le gros du travail.
Externaliser le traitement des bases de données
Je dois avouer que l’externalisation d’une base de données a été l’un de mes hobbies pendant plusieurs années et je continue à la pratiquer allègrement.
Voilà plusieurs années, j’ai écrit un article intitulé « Externaliser le traitement des bases de données« .
Cet article traitait de certains des points touchant à l’externalisation du traitement des bases de données, éclairait votre choix, et décrivait les principaux aspects de la mise en oeuvre. Il était accompagné d’un exemple de processus d’externalisation. Bien entendu, ce code visait à démontrer les concepts de l’externalisation, et non à fournir du code de production débouchant sur une application concrète.
Les avantages potentiels de l’externalisation sont nombreux. La maintenance est facilitée du fait que les structures de fichiers sont définies dans un minimum d’endroits, et la performance est accrue du fait que le traitement d’un fichier particulier dans un job n’a lieu que dans un emplacement : autrement dit, une seule voie de données ouverte au lieu de plusieurs. De plus, vous avez désormais un ensemble de sous-procédures appelables de n’importe quelle interface client, de sorte que l’impact des futurs changements de base de données reste minime.
Dans cet article, je vais plus loin : je fournis un exemple concret d’externalisation d’une base de données, et j’y ajoute un générateur qui fait 90 % de votre travail.
Vous pouvez télécharger l’exemple de code utilisé dans cet article, ainsi que le code du générateur sur Downloads (comconadvisor.com)
Une récapitulation utile
Voici les principaux points de mon précédent article :
• L’externalisation signifie que tout l’accès à la base de données se fait par des procédures publiées communes. Les règles de la base de données sont codées en un seul endroit. Tous les programmeurs (RPG, Java, PHP, etc.) utilisent les mêmes procédures pour accéder à la base de données.
• Les programmes client ignorent totalement la structure de la base de données. Tout l’accès aux données, en entrée et sortie, se fait par des sous-procédures « publiées » —getters et setters.
• Les sous-procédures d’externalisation sont placées dans un programme de service atteint directement par le job client.
• L’ I/O base de données, la validation des données et le traitement des erreurs ont lieu dans un endroit et un seul. De sorte que, quand vous écrivez des programmes client différents, la maintenance de la base de données garde son intégrité.
• Les changements de la base de données ont beaucoup moins d’impact parce qu’ils ne sont effectués qu’en un seul endroit.
• Le traitement de la base de données étant encapsulé dans des sous-procédures, il faut souligner qu’une sous-procédure peut être appelée tout aussi facilement d’une procédure stockée SQL ou d’une méthode Java, que d’un programme RPG.
• Vous devez pouvoir signaler au client tout incident ou anomalie (par exemple, enregistrements en double, problème de maintenance simultanée). La technique est celle d’un module de traitement des messages qui stocke ces derniers : s’il manque quelque chose, un message est ajouté à la liste stockée. Des procédures permettent d’effacer le message stocké, de déterminer combien de messages sont stockés, d’ajouter et d’extraire des messages. Après avoir appelé les routines d’externalisation, le programme client doit repérer la présence de messages et les traiter comme il se doit.
Utiliser les routines d’externalisation
La figure 1 donne un aperçu du format des différentes sous-procédures d’externalisation. Reportez-vous aux renvois :
A. La directive include (copy) incorpore tous les prototypes et définitions de modèles requis.
B. Les définitions de structures requises sont basées sur des modèles.
C. L’élément à traiter est instancié. C’est-à-dire qu’une image des données requises est stockée et un handle (persistId) est renvoyé. Ce handle permettra d’identifier les référencesfutures aux données instanciées.
D. Les getters peuvent concerner des structures (get_Product_Data) ou des valeurs individuelles (get_stock_On_Hand).
E. Les setters peuvent concerner des structures (set_Product_Data) ou des valeurs individuelles (set_selling_Price).
F. Une fois que tous les getters et setters nécessaires ont été appelés, les données instanciées peuvent être mises dans la base de données ou supprimées.
G. Le handle est libéré.
La figure 1 montre les sous-procédures d’externalisation de base. Nous verrons aussi les quick getters et comment obtenir des listes de données.
Le processus
Que se passe-t-il en coulisse ? La routine d’externalisation pour une table (fichier) a un espace utilisateur dans lequel elle stocke des images de toutes les lignes (enregistrements) requises. Un peu comme une matrice d’images d’enregistrements. Ne vous souciez pas de gérer ces espaces utilisateur. Avec ce processus, tout le traitement de l’espace utilisateur (et le traitement des pointeurs correspondant) est encapsulé dans des procédures standard, de sorte que vous n’ayez jamais à le voir – sauf si vous le voulez vraiment.
Voici les principales étapes du processus :
• Un élément est instancié (la new_ subprocedure est appelée), et les données requises pour cet élément (dans ce cas, la ligne provenant d’une table) sont stockées dans un espace utilisateur.
• Le client appelle les getters et setters. Ces sous-procédures échangent simplement les données entre le programme client et l’image stockée dans l’espace utilisateur (c’est-à-dire, un setter change les données dans l’image stockée dans l’espace utilisateur, pas dans la table).
• Mettre l’élément. Ajouter, mettre à jour, ou supprimer les données (pour l’élément) dans l’élément espace utilisateur dans la table.
• Libérer l’élément. Libérer l’emplacement (slot) dans l’espace utilisateur.
En coulisse
Comme pour tous les processus de ce genre, quelques règles standard s’imposent :
• Dans la base de données, chaque table contient la définition d’une colonne nommée changeNo. Cette colonne sert, dans le cadre d’un processus de verrouillage d’enregistrement interne, à s’assurer qu’une demande de mise à jour ou de suppression s’applique bien à la version correcte/originale de la ligne. Chaque fois qu’une ligne est mise à jour, le numéro de changement est incrémenté.
• Les sous-procédures d’externalisation seront contenues dans un ou plusieurs modules dans un ou plusieurs programmes de service. Chaque programme de service doit contenir une copie d’un module spécial. Le nom du module est sans importance, mais je l’appelle FILE00A dans le reste de cet article.
FILE00A contient des sous-procédures privées (ou internes) pour gérer l’externalisation, y compris la logique des pointeurs, la gestion des espaces utilisateur, les time outs, le verrouillage des enregistrements, le traitement des erreurs de fichiers [par exemple getInstance(), putInstance(), getHandle(), releaseHandle(), setHandleLastUsed()]. Ces sous-procédures contiennent le « gros du travail » et ne doivent pas être exportées du programme de service – elles ne doivent être appelées que par les sous-procédures d’externalisation. Beaucoup de ces sous-procédures internes font des rétro-rappels (callbacks) vers des sous-procédures dans les modules d’externalisation. Ne vous préoccupez pas du contenu de FILE00A. Il contient les sous-procédures encapsulées appelées à partir d’un module d’externalisation.
• Chaque module d’externalisation inclut le membre PFILESTD. Lui-même inclut les D specs et le code communs à chaque module d’externalisation. Bien que le code puisse être identique dans chaque module, la version compilée produira des résultats différents – par exemple, une structure de données basée sur une définition de fichier externe (nous verrons bientôt un exemple).
• Chaque module d’externalisation inclut le membre STDHSPEC. Lui-même inclut une spécification d’en-tête éventuelle pour les modules dans le programme de service des procédures de fichiers.
• Bien que les sous-procédures d’externalisation pour une table puissent être codées dans plus d’un module, je préfère m’en tenir à un seul, sauf si sa taille excessive gêne la maintenance.
Il faut aussi considérer où les sources sont stockées et le langage de liage (binder language), mais j’y reviendrai quand nous examinerons les exigences pour générer un module d’externalisation.
Un module d’externalisation
Voyons comment coder un module d’externalisation qui traite des requêtes pour des données produits. Ce module est nommé FILE01A et il a un membre correspondant nommé PFILE01A, qui inclut les prototypes et les définitions de modèles concernant le module d’externalisation.
Prototypes et modèles
Le membre PFILE01A contient les prototypes pour les procédures exportées présentes dans le membre FILE01A. Il contient aussi les définitions de modèles des structures, champs autonomes, ou constantes nommées, susceptibles d’être référencés par des programmes client.
La figure 2 montre la définition d’une structure utilisée pour obtenir et définir des données produit. À noter ce qui suit :
• Toutes les colonnes de la table Product ne sont pas incluses dans la structure de données.
• La colonne category_Description est extraite d’une table Category.
• La colonne totalProfit est calculée.
Dans la version 6.1 (ou ultérieure) de l’OS IBM i, les modèles de structure de données sont définis à l’aide du mot-clé TEMPLATE. Avant la 6.1 elles sont définies comme des structures de données qualifiées et sont basées sur un pointeur « fictif ». Passons au module FILE01A.
Définitions globales
Un module d’externalisation contient les définitions globales communes à toutes les procédures du module, comme le montre la figure 3. Reportez-vous aux renvois :
A. Le module commence par une directive include pour la spécification d’en-tête standard.
B. Le format d’enregistrement du fichier reçoit un nom standard (putRecord).
C. Ce sont les directives include pour les membres protoFile et pFileStd. protoFile contient les directives include pour tous les membres protoType pour le programme de service (par exemple, PFILE00A, PFILE01A etc.). Cet include de pFileStd inclut les définitions D spec communes à tous les modules d’externalisation mais qui restent encore à définir dans chaque module (par exemple, la définition d’une base de données faite un utilisant un likeRec basé sur le format putRecord).
D. Les constantes nommées contiennent les noms des espaces utilisateur concernés par ce processus table/externalisation.
E. C’est la définition de n’importe quelle matrice de structure de données utilisée dans l’extraction des listes.
F. C’est un autre include de pFileStd. Celui-ci amène du code standard au lieu de définitions D specs standard.
La figure 4 montre une partie seulement du code standard dans le membre include pFileStd. Les D specs sont incluses avec la directive include en C de la figure 3, et la sous-procédure getRowAndLock est incluse en F de la figure 3. Bien que le code soit exactement le même dans chaque module d’externalisation, il est inclus via un membre copy parce qu’il référence des définitions F et D spec, qui seront différentes dans chaque module. Reportez-vous aux renvois :
A. lockRecord est une structure de données basée sur le format du fichier traité. Rappelons que putRecord est un renommage du format d’enregistrement pour la table traitée (B en figure 3).
B. key est une structure de données définie en externe basée sur la portion clé (key) du fichier traité.
C. setKeyDS() est appelé pour définir les champs clés requis dans la structure de données key (nous y reviendrons).
D. L’opération chain utilise la définition %KDS(Key) pour extraire une ligne du fichier (en utilisant le nom de format putRecord) et pour le placer dans la structure de données lockRecord.
Téléchargez cette ressource
Comment lutter contre le Phishing ?
Dans un environnement cyber en constante mutation, le phishing évolue vers des attaques toujours plus sophistiquées combinant IA, automatisation et industrialisation. Découvrez les réponses technologiques préconisées par les experts Eviden et les perspectives associées à leur mise en œuvre.