web-dev-qa-db-fra.com

Problèmes avec les AND et les OR (COBOL)

J'ai un devoir qui doit être rendu demain et je n'arrive pas à obtenir cette partie. Voir m'a donné un fichier d'entrée avec un tas de noms, dont certains doivent être ignorés, avec des informations supplémentaires sur chacun. J'essayais d'utiliser des ET et des SU pour ignorer les noms dont je n'avais pas besoin et j'ai trouvé ceci.

IF DL-CLASS-STANDING = 'First Yr' OR 'Second Yr' AND
GRAD-STAT-IN = ' ' OR 'X'

Il s'est débarrassé de toutes les personnes sauf une, mais lorsque j'ai essayé d'ajouter une autre série d'ET et de ROS, le programme a commencé à se comporter comme les stipulations où il n'y en avait même pas. 

Ai-je le rendre trop complexe pour le compilateur? Y a-t-il un moyen plus facile de sauter des choses?

36
Kimmy1235

Essayez d’ajouter des parenthèses pour regrouper les éléments logiquement:

IF (DL-CLASS-STANDING = 'First Yr' OR 'Second Yr') AND (GRAD-STAT-IN = ' ' OR 'X')

134
Joel Spolsky

Wow, ça fait si longtemps que je ne me souviens même pas si cette syntaxe est valide ou non :-) Vous voudrez peut-être examiner le développement complet de cette expression abrégée, car le développement ne correspond peut-être pas à ce que vous pensez lorsqu'il y a beaucoup de clauses. Mieux vaut être explicite.

Cependant, ce que je ferais, c’est d’utiliser les variables de niveau 88 pour le rendre plus lisible - 88s étaient des niveaux spéciaux permettant de spécifier directement les conditions dans la division de données plutôt que d’utiliser des conditions explicites dans le code.

En d’autres termes, mettez quelque chose comme ceci dans votre division de données (c’est de mémoire puisque mon seul compilateur COBOL est sur le mainframe au travail et que je pars aujourd’hui).

03  DL-CLASS-STANDING  PIC X(20).
    88 IS-FIRST-YEAR              VALUE 'First Yr'.
    88 IS-SECOND-YEAR             VALUE 'Second Yr'.
03  GRAD-STAT-IN       PIC X.
    88 GRAD-STAT-UNKNOWN          VALUE ' '.
    88 GRAD-STAT-NO               VALUE 'X'.

Ensuite, vous pouvez utiliser les variables de niveau 88 dans vos expressions:

IF (IS-FIRST-YEAR OR IS-SECOND-YEAR) AND (GRAD-STAT-UNKNOWN OR GRAD-STAT-NO) ...

C’est, à mon avis, plus lisible et l’objectif même de COBOL était de ressembler à un anglais lisible, après tout.

27
paxdiablo

La première chose à noter est que le code affiché est le code qui fonctionnait, le code modifié qui ne donnait pas le résultat souhaité n’a jamais été affiché. En addenda, pourquoi, s'il ne restait qu'une personne, aurait-elle besoin d'une plus grande sélection? En résumé, la question qui se pose n’est pas claire: il ne suffit pas de dire: "Je ne sais pas comment utiliser OR en COBOL. Je ne sais pas comment utiliser AND en COBOL".

Au-delà de cela, il y avait deux questions réelles:

  1. Ai-je le rendre trop complexe pour le compilateur? 

  2. Existe-t-il un moyen plus simple de sauter des éléments [existe-t-il un moyen plus clair d’écrire des conditions]?

Pour le premier, la réponse est non, c'est très loin d'être difficile pour le compilateur. Le compilateur sait exactement comment gérer toutes les combinaisons de OR, AND (et NOT, auxquelles nous reviendrons plus tard). Le problème est que l’écrivain/lecteur humain peut coder avec succès une condition telle que le compilateur sache ce qu’il veut, plutôt que de simplement donner le résultat du compilateur en suivant ses règles (sans tenir compte des multiples interprétations humaines possibles d’une ligne) de code)?

La deuxième question devient donc:

Comment puis-je écrire une condition complexe que le compilateur comprendra de manière identique à mon intention en tant qu'auteur et de manière identique pour tout lecteur du code ayant une expérience de COBOL? 

Tout d’abord, une réorganisation rapide du code (de travail) dans la question:

IF DL-CLASS-STANDING = 'First Yr' OR 'Second Yr' 
AND GRAD-STAT-IN = ' ' OR 'X'

Et du code suggéré dans l'une des réponses:

IF (DL-CLASS-STANDING = 'First Yr' OR 'Second Yr') 
AND (GRAD-STAT-IN = ' ' OR 'X')

La deuxième version est plus claire, mais (ou et) elle est identique à la première. Cela n'a pas fait fonctionner ce code, il a permis à ce code de continuer à fonctionner.

La réponse abordait la résolution du problème d'une condition dont la complexité était accrue: crochets/parenthèses (simplifier simplement la complexité est une autre possibilité, mais sans exemple non exploitable, il est difficile de faire des suggestions). 

Le code original fonctionne mais quand il doit être plus complexe, les roues commencent à tomber.

Le code suggéré fonctionne, mais il ne résout pas (totalement) le problème de l'extension de la complexité de la condition, car, en mineur, il répète le problème, entre parenthèses, de l'extension de la complexité de la condition.

Comment est-ce ainsi?

Une condition simple:

IF A EQUAL TO "B"

Une condition légèrement plus complexe:

IF A EQUAL TO "B" OR "C"

Une légère, mais pas complète, simplification de cela:

IF (A EQUAL TO "B" OR "C")

Si la condition doit devenir plus complexe, avec un AND, cela peut être simple pour les humains (le compilateur s'en fiche, on ne peut pas être dupe):

IF (A EQUAL TO "B" OR "C")
AND (E EQUAL TO "F")

Mais qu'en est-il?

IF (A EQUAL TO "B" OR "C" AND E EQUAL TO "F")

Le fait de placer AND dans les crochets a permis de reproduire le problème initial pour les humains. Qu'est-ce que ça veut dire, comment ça marche?

Une réponse est la suivante:

IF (A EQUAL TO ("B" OR "C") AND E EQUAL TO "F")

Peut-être plus clair, mais pas pour tout le monde, et encore une fois, le problème initial existe toujours, en mineur.

Alors:

IF A EQUAL TO "B"
OR A EQUAL TO "C" 

Simplifié, pour la première partie, mais reste ce problème en mineur (ajoutez simplement AND ...), donc:

IF (A EQUAL TO "B")
OR (A EQUAL TO "C")

Menant à:

IF ((A EQUAL TO "B")
OR (A EQUAL TO "C"))

Et:

IF ((A EQUAL TO "B")
 OR (A EQUAL TO C))

Maintenant, si quelqu'un veut augmenter AND, c'est facile et clair. Si cela est fait au même niveau que l'une des pièces d'état, cela s'attache uniquement à cela. Si cela est fait au niveau le plus externe, il s'attache aux deux (tous).

IF (((A EQUAL TO "B")
  AND (E EQUAL TO "F"))
 OR (A EQUAL TO "C"))

ou

IF (((A EQUAL TO "B")
 OR (A EQUAL TO "C"))
AND (E EQUAL TO "F"))

Que se passe-t-il si quelqu'un veut insérer le AND dans les crochets? Eh bien, parce que l'intérieur des crochets est simple, les gens n'ont pas tendance à le faire. Si ce qui est à l'intérieur des crochets est déjà compliqué, il a tendance à être ajouté. Il semble que ce qui est simple par soi-même ait tendance à ne pas être compliqué, alors que ce qui est déjà compliqué (plus d'une chose, pas tout seul) a tendance à être complexifié sans trop de réflexion.

COBOL est une vieille langue. De vieux programmes écrits en COBOL sont toujours en cours d'exécution. De nombreux programmes COBOL doivent être modifiés, ou simplement lire pour comprendre quelque chose, plusieurs fois au cours de leur vie.

Lors du changement de code, en ajoutant quelque chose à une condition, il est préférable que les parties d'origine de la condition n'aient pas besoin d'être "perturbées". Si la complexité est laissée entre crochets, il est plus probable que le code doit être perturbé, ce qui augmente le temps nécessaire pour comprendre (il est plus complexe) et pour changer (davantage de prudence est nécessaire, plus de tests sont nécessaires, car le code est perturbé). .

Beaucoup d'anciens programmes seront des exemples de mauvaise pratique. Pas grand chose à faire à ce sujet, sauf à faire attention avec eux.

Il n'y a aucune excuse pour écrire un nouveau code qui nécessite plus de maintenance et de soins dans le futur que ce qui est absolument nécessaire.

Maintenant, les exemples ci-dessus peuvent être considérés comme étant longs. C'est du COBOL, non? Beaucoup de dactylographie? Mais COBOL offre une grande flexibilité dans la définition des données. COBOL a, dans ce cadre, le niveau 88, le nom de la condition.Voici la définition des données pour une partie de ce qui précède:.

01 A PIC X. 88 PARCEL-IS-OUTSIZED VALUE "B" "C". 01 F PIC X. 88 POSTAGE-IS-SUFFICIENT VALUE "F".

IF PARCEL-IS-OUTSIZED
AND POSTAGE-IS-SUFFICIENT

If condition
.

If condition = If (condition) = If ((condition1) operator (condition2))...

IF NOT A EQUAL TO B
IF A NOT EQUAL TO B

IF (NOT (A EQUAL TO B)), remembering that this is just IF condition

IF ( ( ( condition1 )
    OR ( condition2 ) )
AND 
     ( ( condition3 )
    OR ( condition4 ) ) )

Si les conditions ne sont pas simplifiées, alors la compréhension du code est plus difficile. Changer le code est plus difficile. Pour les personnes qui apprennent le COBOL, garder les choses simples est un avantage à long terme pour tous.

If conditions are not simplified, then understanding the code is more difficult. Changing the code is more difficult. For people learning COBOL, keeping things simple is a long-term benefit to all.

7
Bill Woodger

En règle générale, j'évite l'utilisation de AND si possible. Le travail des IF imbriquées est tout aussi facile à lire et, avec une utilisation judicieuse de 88 niveaux, il n’est pas nécessaire d’aller très loin. Cela semble tellement plus facile à lire, du moins d'après mon expérience:

05  DL-CLASS-STANDING            PIC X(20) VALUE SPACE.
    88  DL-CLASS-STANDING-VALID  VALUE 'First Yr' 'Second Yr'.
05  GRAD-STAT-IN                 PIC X     VALUE SPACE.
    88  GRAD-STAT-IN-VALID       VALUE SPACE 'N'.

Alors le code est aussi simple que cela:

IF DL-CLASS-STANDING-VALID
    IF GRAD-STAT-IN-VALID
        ACTION ...  .
0
Sean Elgin