LCP Warnier

La logique de construction des programmes

L'ingénieur Jean-Dominique Warnier
Jean-Dominique Warnier


Jean-Dominique WARNIER était un ingénieur de chez Bull. Au début des années 1970 il commença à publier de nombreux ouvrages concernant l'algorithmie et ses méthodes novatrices en matière de programmation. L'un des plus retentissants livres de Warnier est son fameux « Logique de construction des programmes », plus connu sous l'abréviation L.C.P. La logique de construction des programmes est avant tout une méthode qui définit un programme sous trois aspects : son début, le traitement, sa fin.

- C'est dans la partie « début » que l'on fera toutes les initialisations, les ouvertures de fichiers, les accès aux fichiers pré-requis et tout ce qu'il est néssaire de faire avant que le traitement répétitif ne commence.

- Le traitement contient la suite des instructions qui constituent le traitement proprement dit.

- La fin regroupe toutes les opérations de finition avant de quitter le programme. On y rencontre des affichages de compteurs et la fermeture de tous les fichiers.

Les instructions relatives à chacun de ces trois aspects sont mises dans une accolade ouvrante. C'est la caractéristique de la méthode LCP.

La notation de la méthode LCP avec les accolades
Notation caractéristique de LCP

Ceux qui ont lu mon dossier sur les arbres programmatiques remarqueront que quand on retourne l'illustration de 90 degrés vers la droite on retrouve grosso-modo la structure d'un arbre programmatique. Mais détrompez-vous ! La méthode Warnier n'est pas faite pour faire de la programmation structurée avec des arbres programmatiques. Le sens de lecture de la méthode L.C.P. est le suivant :

Sens de lecture de la méthode LCP de JD Warnier
Se lit de haut en bas



Un programme écrit selon la méthode Warnier est fait pour être lu de haut en bas, il est linéaire et il ne possède que peu de PERFORM.

Ecriture d'un programme avec la méthode Warnier

Si la notation avec les accolades n'est là que pour le côté mnémonique elle est cependant très pratique pour représenter les instructions conditionnelles, les alternatives. En effet, le VRAI sera toujours mis en face de la branche du haut de l'accolade et le FAUX sera toujours en face de la branche du bas de l'accolade.

Voici comment sera donc représentée une condition pour un traitement simple permétant juste de compter les enregistrements d'un fichier :

La notation d'une alternative avec la méthode LCP
La condition vraie en haut de l'accolade, la condition fausse en bas

Mais la vraie force de la programmation Warnier réside dans la gestion des ruptures, ce qui est relativement courant en informatique de gestion. Voyons comment on va écrire un programme COBOL avec la méthode Warnier au travers d'un exemple.

Soit un programme devant traiter un fichier avec 3 niveaux de rupture sur les zones suivantes : zone1, zone2, zone3.

On ne déclare qu’une seule fois la description du fichier. C'est un avantage par rapport à d'autres méthodes qui nécessitent de déclarer deux fois la description du fichier afin d'effectuer des comparaisons pour déterminer les ruptures. Ici, les ruptures seront décrites à part dans la working et avec une description en cascade caractéristique.

LFICIN correspond à l’enregistrement lu.

Description en working des zones de rupture :

* Zones de rupture de l'enregistrement lu
01  LRUPT.
    05  LRUPT-zone3.
        10  LRUPT-zone2.
            15  LRUPT-zone1.
                20  LZONE1      PIC XXXX.
            15  LZONE2          PIC XX.
        10  LZONE3              PIC XXXXXXXX.

* Zones de rupture de l'enregistrement précédent
01  WRUPT.
    05  WRUPT-zone3.
        10  WRUPT-zone2.
            15  WRUPT-zone1.
                20  WZONE1      PIC XXXX.
            15  WZONE2          PIC XX.
        10  WZONE3              PIC XXXXXXXX.

Les ruptures sont déterminées par comparaison des zones globales WRUPT-... et LRUPT-..., jamais par comparaison des variables de bas niveau décrites avec des PICtures.

On déterminera donc les ruptures en effectuant les comparaisons suivantes :
    - Rupture de premier niveau si LRUPT-zone1 différent de WRUPT-zone1
    - Rupture de second niveau si LRUPT-zone2 différent de WRUPT-zone2
    - Rupture de 3° niveau si LRUPT-zone3 différent de WRUPT-zone3

Vous noterez qu'avec la description en cascade un simple changement de LZONE1 (qui est le premier critère de tri) entraine automatiquement les ruptures à tous les niveaux.

Structure du programme

♦ initialisations (partie « début »)
            Ouverture du fichier.
     MOVE   LOW-VALUE    TO    WRUPT.
            Première lecture AT END MOVE HIGH-VALUE TO LFICIN.
     MOVE   FIC-ZONE1    TO    LZONE1.
     MOVE   FIC-ZONE2    TO    LZONE2.
     MOVE   FIC-ZONE3    TO    LZONE3.

DEBUT-CYCLE. (partie « traitements »)

♦ RUPT-DEBUT-zone1.
   Si LRUPT-zone1 = WRUPT-zone1  GO TO   RUPT-DEBUT-zone2.
                 insérer les traitements début rupture 1

♦ RUPT-DEBUT-zone2.
   Si LRUPT-zone2 = WRUPT-zone2  GO TO   RUPT-DEBUT-zone3.
                 insérer les traitements début rupture 2

♦ RUPT-DEBUT-zone3.
   Si LRUPT-zone3 = WRUPT-zone3  GO TO   TRAIT-DETAIL.
                 insérer les traitements début rupture 3

♦ TRAIT-DETAIL.
   Insérer les traitements détail
       Ici on travaille avec les zones de l'enregistrement lu

♦ Sauvegarde globale des zones de ruptures lues dans les zones W, lecture suivante et alimentation des zones de rupture
          MOVE   LRUPT        TO    WRUPT.
          lecture suivante AT END MOVE HIGH-VALUE to LFICIN.
    MOVE   FIC-ZONE1    TO    LZONE1.
    MOVE   FIC-ZONE2    TO    LZONE2.
    MOVE   FIC-ZONE3    TO    LZONE3.

♦ RUPT-FIN-zone3.
   Si LRUPT-zone3 = WRUPT-zone3  GO TO RUPT-FIN-zone2.
                insérer les traitements fin rupture 3

♦ RUPT-FIN-zone2.
   Si LRUPT-zone2 = WRUPT-zone2  GO TO RUPT-FIN-zone1.
                insérer les traitements fin rupture 2

♦ RUPT-FIN-zone1.
   Si LTRUPT-zone1 = WRUPT-zone1  GO TO TRAIT-ERREUR.
                insérer les traitements fin rupture 1

♦ TRAIT-ERREUR.
   si erreur
        PERFORM traitement-erreur
   finsi

♦ Si LFICIN NOT = HIGH-VALUE
       GO TO DEBUT-CYCLE.

♦ Traitement final (partie « fin »)
        o    Ecriture compte rendu de traitement (compteurs)
        o    Fermeture des fichiers
        o    Display de fin de traitement
        o    STOP RUN. (ou GOBACK)


Problèmes posés par cette méthode :
-    On utilise quelques GO TO, ce qui ne plait pas aux puristes de la programmation structurée avec des PERFORM.

Avantages :
-    Le programme est linéaire et séquentiel (il se lit du début à la fin, de haut en bas)
-    Plus de traitements imbriqués dans un énorme PERFORM UNTIL
-    Plus de calcul du chemin à l’avance et plus d’utilisation de Tops compliqués
-    Programmation plus souple et plus naturelle.
-    La détermination des ruptures ne se fait pas par comparaison zone à zone mais uniquement par des MOVE.

Mélange de plusieurs méthodes de programmation

Il est possible d'intégrer quelques éléments empruntés à la méthode CORIG pour rendre le programme plus structuré en codant chaque paragraphe RUPT-DEBUT-... ou RUPT-FIN-... en tant que brique indépendante.

Voici ce que ça pourrait donner :

♦ initialisations (partie « début »)
               Ouverture du fichier.
      MOVE   LOW-VALUE    TO    WRUPT.
               Première lecture AT END MOVE HIGH-VALUE TO LFICIN.
      MOVE   FIC-ZONE1    TO    LZONE1.
      MOVE   FIC-ZONE2    TO    LZONE2.
      MOVE   FIC-ZONE3    TO    LZONE3.

DEBUT-CYCLE. (partie « traitements »)

♦ RUPT-DEBUT-zone1.
  Si LRUPT-zone1 = WRUPT-zone1  GO TO   FIN-RUPT-DEBUT-zone1.
                 insérer les traitements début rupture 1
  FIN-RUPT-DEBUT-zone1.
       EXIT.

♦ RUPT-DEBUT-zone2.
  Si LRUPT-zone2 = WRUPT-zone2  GO TO   FIN-RUPT-DEBUT-zone2.
                 insérer les traitements début rupture 2
  FIN-RUPT-DEBUT-zone2.
       EXIT.

♦ RUPT-DEBUT-zone3.
  Si LRUPT-zone3 = WRUPT-zone3  GO TO   FIN-RUPT-DEBUT-zone3.
                 insérer les traitements début rupture 3
  FIN-RUPT-DEBUT-zone3.
       EXIT.

♦ Insérer les traitements détail
 TRAIT-DETAIL.
       Ici on travaille avec les zones de l'enregistrement lu

♦ Sauvegarde globale des zones de ruptures lues dans les zones W, lecture suivante et alimentation des zones de rupture
          MOVE   LRUPT        TO    WRUPT.
          lecture suivante AT END MOVE HIGH-VALUE to LFICIN.
    MOVE   FIC-ZONE1    TO    LZONE1.
    MOVE   FIC-ZONE2    TO    LZONE2.
    MOVE   FIC-ZONE3    TO    LZONE3.

♦ RUPT-FIN-zone3.
  Si LRUPT-zone3 = WRUPT-zone3  GO TO fin-RUPT- FIN-zone3.
                insérer les traitements fin rupture 3
  FIN-RUPT- FIN-zone3.
       EXIT.

♦ RUPT-FIN-zone2.
  Si LRUPT-zone2 = WRUPT-zone2  GO TO fin-RUPT- FIN-zone2.
                insérer les traitements fin rupture 2
  FIN-RUPT- FIN-zone2.
       EXIT.

♦ RUPT-FIN-zone1.
  Si LTRUPT-zone1 = WRUPT-zone1  GO TO fin-RUPT- FIN-zone1.
                insérer les traitements fin rupture 1
  FIN-RUPT- FIN-zone1.
       EXIT.

♦ TRAIT-ERREUR.
si erreur
        PERFORM traitement-erreur
   finsi

♦ Si LFICIN NOT = HIGH-VALUE
       GO TO DEBUT-CYCLE.

♦ Traitement final (partie « fin »)
        o    Ecriture compte rendu de traitement (compteurs)
        o    Fermeture des fichiers
        o    Display de fin de traitement
        o    STOP RUN. (ou GOBACK)