The long and winding road - moderniser le 5250

 The long and winding road

moderniser le 5250


Quand on parle de moderniser une application 5250, la conversation part presque toujours sur le front : 

  • quel framework, 

  • quelle ergonomie, 

  • quel prestataire. 

  • …

C'est mettre la charrue avant les bœufs. 

Un écran 5250 n'est pas qu'une interface : il contient, mélangées dans le même source, des règles de gestion, des contrôles, de l'accès aux données et de la navigation. 

Si on refait l'écran en web sans démêler tout cela, on obtient un 5250 qui a changé de décor, avec les mêmes limites et un coût de maintenance supplémentaire.

Bref, comme l’aurait dit le grand William Shakespeare : “Beaucoup de bruit pour rien” …


La démarche décrite ici est volontairement simple KISS, soit : “Keep It Simple and Stupid”.

Séparer ce qui est de la règle de gestion de ce qui est de la présentation, puis exposer les règles comme des services. 

Le front vient en dernier, et il devient presque un détail.

Les principes

1. Rassembler et isoler les règles de gestion

Premier travail, dans le source existant : repérer les règles de gestion et les regrouper dans des sous-routines, en raisonnant par points d'entrée standardisés, ceux que tout programme écran possède de fait :

  • initialisation ;

  • avant lecture en base ;

  • avant affichage de l'écran ;

  • après validation par l'utilisateur ;

  • etc.

Ceux qui ont pratiqué Synon/2E y reconnaîtront les user points. Ben, oui, on ne se refait pas. Je n’ai pas passé 15 ans sur cet AGL mourant pour ne pas retenir ce qui étaient de bons principes.

L'idée est la même : donner à chaque règle une place prévisible. Cette étape se fait encore dans le programme d'origine, sans rien casser, et elle suffit déjà à rendre le code lisible.

2. Externaliser les règles dans des procédures

Les sous-routines sortent ensuite du programme pour devenir des procédures. 

La règle d'or : une procédure implémente un but fonctionnel. 

Le piège classique est la procédure fourre-tout, qui prend dix paramètres et dont le comportement change selon un code action. On a alors simplement déplacé le plat de spaghettis. Si on ne sait pas nommer le but de la procédure en une phrase, c'est qu'elle en fait trop.

3. Les packager : programmes ou service programs ?

Ma première idée, naïve, était « une fonction = un programme », ce qui a l'avantage d'une granularité maximale et d'une exposition simple.

À l'usage, ça pose plusieurs problèmes : des centaines d'objets à gérer, un coût d'appel et d'activation à chaque exécution, et une maintenance plus lourde.

En ILE, le mécanisme natif est le service program : un module regroupant des procédures exportées, chacune gardant son but fonctionnel. 

On regroupe par domaine métier (clients, commandes, tarifs), pas par écran. Ca respecte une organisation inspirée du modèle objet.

Les procédures restent appelables depuis les anciens programmes 5250, ce qui permet une migration progressive, et la même procédure sert l'écran et le web. 

Les deux options sont défendables, mais je recommande le service program. Quitte à moderniser, autant y aller franchement !

4. En faire des services web

Les procédures exportées peuvent ensuite être exposées en services web, par exemple avec IWS (Integrated Web Services), ou avec des solutions open source écrites en RPG comme ILEastic et noxDB pour la gestion du JSON. 

Le choix dépend de la release, du parc et des compétences. 

L'important est que la règle de gestion soit écrite une seule fois, et qu'elle reste dans le monde IBM i.

Les pièges : ce que le 5250 faisait sans qu'on le voie

Le 5250 cachait beaucoup de choses. En les retirant, on les découvre.

L'état. Un job 5250 conserve tout : variables de travail, sous-fichier chargé, indicateurs, position du curseur. 

Sur le web, chaque appel est indépendant, et rien ne garantit qu'il retombe dans le même job. 

Le principe : l'état vit chez le client, qui renvoie le contexte nécessaire à chaque appel.
Si on choisit un état côté serveur (table, identifiant de session), que ce soit un choix assumé et non un héritage. La pagination du sous-fichier devient une pagination par clé (« les n suivants après telle clé », l'équivalent d'un SETLL/READ) plutôt qu'un OFFSET, qui devient de plus en plus coûteux en SQL.

La concurrence. En 5250, on verrouille l'enregistrement au CHAIN/READ, souvent juste avant le UPDATE. 

Sur le web, l'utilisateur peut garder son formulaire ouvert une heure, et on ne peut pas tenir un verrou aussi longtemps. 

La réponse est le verrou optimiste : une version ou un timestamp est lu avec la donnée, puis renvoyé à la mise à jour. S'il ne correspond plus, on refuse (HTTP 409 ou 412) et l'utilisateur voit que la donnée a changé.
Selon la release, DB2 for i sait gérer un ROW CHANGE TIMESTAMP ; sinon, une colonne de version maintenue par la couche d'accès fait l'affaire.

Le commit control. Aucune transaction ne doit rester ouverte entre deux appels. 

Une opération métier doit tenir dans un seul appel atomique, ou être découpée explicitement (brouillon, statut), jamais en transaction à cheval. Il faut aussi anticiper les relances côté client (réseau, double clic) : une clé d'idempotence évite de créer deux fois la même commande.
Attention enfin aux commitment définitions dans un pool de jobs réutilisés : rien ne doit rester ouvert d'un appel à l'autre.

La sécurité. Sous quel profil s'exécute l'appel ?
C'est la question centrale.
Un profil par utilisateur est idéal pour l'audit mais plus lourd à gérer ; un profil applicatif avec l'utilisateur réel passé en paramètre est plus simple mais impose de journaliser l'utilisateur réel, sinon la traçabilité est perdue.
Dans les deux cas, on évite le profil technique aux autorités larges, et on réserve les autorités adoptées à quelques procédures, avec parcimonie. 

Mais ceci est un autre sujet : la sécurité des objets sur le serveur.

Dernier point : le DDS imposait des contrôles de format de fait, et le service doit désormais tout revalider côté serveur (types, longueurs, requêtes SQL paramétrées).

Les tests de caractérisation. Avant tout refactoring, il faut capturer le comportement actuel : jeux d'entrées, sorties et état de la base avant/après, pour pouvoir comparer une fois le code découpé.
Ce n'est pas un test de la règle idéale mais de la règle réelle, bugs compris. Sans cela, on ne sait pas si l'on a cassé quelque chose.
L'outillage dépend des habitudes ( RPGUnit , iUnit , solutions d’éditeurs du marché, voire scripts maison).

Le contrat d'échange : ce qui permet de passer la main

C'est le point qui rend l'étape suivante possible. Si le contrat entre IBM i et le front est propre, les deux équipes travaillent de façon indépendante.
S'il est flou, la coordination ne s'arrête jamais.

Contract-first. On écrit la spécification OpenAPI avant le code. Elle permet de travailler en parallèle (mock côté web, implémentation côté IBM i), de générer la documentation et des clients typés, et elle matérialise la frontière entre les équipes.
On évite de laisser le contrat dériver mécaniquement de la signature RPG, au risque d'exposer des noms de zones sur 10 caractères et des structures internes.

Penser en actions métier, pas en CRUD. 

Les points d'entrée standardisés de l'étape 1 se retrouvent dans le contrat :

  • « init » et « avant affichage » donnent un GET qui renvoie les valeurs par défaut, les listes de valeurs et les métadonnées de chaque champ.
    Les attributs d'affichage du 5250 (protégé, obligatoire, masqué) deviennent des propriétés du champ dans la réponse, ce qui évite de ré-implémenter ces règles côté front ;

  • « après validation » donne un appel de validation à blanc (sans écriture), puis l'appel qui enregistre.
    Le front peut ainsi afficher les erreurs avant le commit.

Un modèle d'erreur structuré. 

À la place des indicateurs 90-99 et de la message queue, une réponse d'erreur donne, pour chaque problème : un code stable, un message, le champ concerné et une sévérité (erreur bloquante ou avertissement).

  • Plusieurs erreurs peuvent figurer dans la même réponse, là où le 5250 n'en affichait souvent qu'une à la fois.

  • Les statuts HTTP sont cohérents : 400 pour une requête mal formée, 422 pour une règle de gestion violée, 409 pour un conflit de version, 403 pour l'autorité, 404 pour l'inexistant.

  • Un format standard existe (RFC 9457, « problem details »), autant s'en inspirer.

  • Les MSGID des fichiers de messages existants font d'excellents codes d'erreur, le texte étant résolu à l'appel : on réutilise l'existant et on conserve la traduction.

  • Les confirmations (le classique « F10 pour confirmer ») deviennent des avertissements que le client renvoie avec un indicateur de confirmation.

Les pièges de données. Quatre classiques :

  • les montants : éviter les nombres flottants JSON (chaînes, ou entiers en centimes) ;

  • les dates : ISO 8601, et décider du sort des dates « vides » (0001-01-01, 0, blancs) ;

  • les CHAR avec blancs à droite : les rogner, et distinguer vide de NULL.
    Le gros dilemme classique de l’AS400 avec ses fichiers PF où le “blanc” et le “zéro” pouvaient être une absence d’information ou une information → valeur nulle, valeur blanc;

  • le CCSID : UTF-8 de bout en bout, et attention aux conversions EBCDIC.

L'évolution. On versionne dès le départ (/v1) et on n'autorise que des changements compatibles à l'intérieur d'une version.

Et le front ?

Ce n'est pas l'objet de cet article, et c'est volontairement le choix le plus remplaçable. 

Avec un contrat REST propre, le front devient interchangeable.
Le bon critère n'est pas la tendance du moment, mais ce que l'équipe web maîtrise déjà :

  • React + TypeScript : le plus courant, avec le plus grand vivier de développeurs ;

  • Angular : plus cadré, bien adapté aux applications de gestion à gros formulaires et aux équipes nombreuses ;

  • Vue : plus simple à prendre en main pour une petite équipe ;

  • HTMX et templates côté serveur : pour rester dans l'esprit KISS sans SPA, au prix d'une couche serveur qui produit le HTML.

Dans tous les cas, on peut intercaler un petit BFF (Backend For Frontend, en Node ou Java) entre l'IBM i et le navigateur, pour l'authentification, l'agrégation d'appels et l'adaptation des formats, plutôt que d'exposer directement les services IBM i. 

Et on se garde de reproduire l'écran 5250 à l'identique dans le navigateur : c'est une occasion de repenser l'ergonomie, pas de la figer.

Conclusion de la partie technique

Moderniser du 5250 en web n'est pas d'abord un choix technologique.
C'est un travail de séparation des responsabilités : isoler les règles de gestion, leur donner une interface claire, les exposer, puis laisser chaque équipe faire son métier.
Le jour où le framework front change (et il changera), les règles de gestion, elles, n'auront pas bougé.


Euh... Avec des vrais mots de français, ça donne quoi ?


Votre système d’information a des décennies. Ce n’est pas une malédiction, c’est le signe que votre système est en adéquation avec votre activité.


Tout jeter à la poubelle pour prendre un “progiciel sur l’étagère” revient à chercher le dahu.



Les plus savoyards d’entre vous la savent déjà : le dahu n’existe pas.


Idem pour le “progiciel-sur-l’étagère-qui-doit-coller-à-votre-cœur-de-métier-pour-continuer-à-vous-démarquer-de-la-concurrence-qui-a-adopté-elle-aussi-un-progiciel-sur-l’étagère-et-que-ça-doit-être-le-même-que-vous…”


Mais... comment arrivez-vous à être différent des autres ?

Vous ne le serez pas !

Vous allez vous retrouver avec une somme astronomique de spécifiques pas toujours connus, pas toujours documentés.

Donc obligés de fouiller dans les programmes pour retrouver la mémoire de plusieurs décennies de développement.


Prendre du progiciel pour toutes les fonctions annexes à votre activité, d’accord, c’est une bonne approche.


Pour votre métier de base, permettez-moi d’en douter…


Ce que je propose dans cet article peut sembler long et complexe. Ce n’est qu’une impression, car vous pouvez moderniser au fil de l’eau : saupoudrer des tâches décrites plus haut dans vos maintenances importantes ou vos projets



Après le dahu, permettez-moi une comparaison.

La 205 GTI est la meilleure petite sportive que j’ai connu (non, je ne suis pas un boomer, mais un “génération X”)


Toutefois, elle n’est plus adaptée à notre quotidien.

Alors, …


  • Je lui colle des pneus plus modernes pour améliorer la motricité.

  • Ensuite, un ABS dernière génération

  • Un moteur électrique pour rouler tranquillou dans Paris

  • Des phares et feux à LED, car ça éclaire mieux et on est plus visible.

  • Je garde ma sono Pioneer d’époque qui crachait 4 x 50 W. Il fallait bien ça pour lutter avec le moteur !

  • A la place du lecteur de K7 : un DAC audio compact, comme ça, j’aurais mes 2 200 albums


Et je mets toujours du Motörhead pour faire Paris ←→ Marseille sur le réseau secondaire.



Conclusion finale



Je garde une 205, car c’est LA voiture qui me convenait parfaitement.



Je la mets au goût du jour pour la sécurité et les contraintes actuelles sans sacrifier son ADN.


Et ZUT pour les voitures “modernes”.




Commentaires

Articles les plus consultés