01 EOF-SW PIC X(01) VALUE 'N'.
88 EOF VALUE 'Y'.
With additional values we can encode further information about the
state of the file:
01 INPUT-STATUS-FLAG PIC X(01) VALUE 'A'.
88 INPUT-FILE-UNOPENED VALUE 'A'.
88 INPUT-FILE-UNREAD VALUE 'B'.
88 INPUT-FILE-STARTED VALUE 'C'.
88 INPUT-FILE-EOF VALUE 'D'.
88 INPUT-FILE-CLOSED VALUE 'E'.
By convention, a switch has two possible values, and a
flag has more than two possible values.
Whenever possible, access flags and switches only through their 88-levels. The name of such a variable shouldn't even appear in the PROCEDURE DIVISION (except perhaps in a MOVE statement which copies one flag or switch to another).
Suppose you're reading somebody else's program and find:
[Warning: bad code ahead]
IF INPUT-STATUS-FLAG = 'C'
[do something...]
Are you going to know what that means? What if the code had read:
IF INPUT-FILE-STARTED
[do something...]
Now isn't that nicer?
The same considerations apply when you assign values to a logical variable. MOVE 'B' TO INPUT-STATUS-FLAG doesn't tell you much, except for what you can guess from the context. SET INPUT-FILE-UNREAD TO TRUE is more informative.
Now suppose it's 2:00 AM and you're trying to patch a miscreant program so that the cycle can finish. Oh, there it is -- somebody forgot to reset USOC-FOUND-SW. OK, throw in a quick MOVE 'N' TO USOC-FOUND-SW, compile, link, release, and go back to bed.
Oops. That should have been a '0', not a 'N'. Too bad you didn't code SET USOC-NOT-FOUND TO TRUE.
Poor names increase the danger. Suppose our INPUT-STATUS-FLAG example had looked like this:
[Warning: bad code ahead]
01 INPUT-STATUS-FLAG PIC X(01) VALUE 'A'.
88 NOT-OPENED-YET VALUE 'A'.
88 JUST-OPENED VALUE 'B'.
88 AT-LEAST-ONE-RECORD-READ VALUE 'C'.
88 NO-MORE-RECORDS VALUE 'D'.
88 INPUT-CLOSED VALUE 'E'.
These names are all meaningful, but they bear no obvious relation to
each other. If the program sets AT-LEAST-ONE-RECORD-READ to TRUE, will
you recognize that the result affects a later test for JUST-OPENED?
Choose your 88-level names carefully to minimize this danger. For flags, add nice long prefixes to the names, so that you can recognize them as members of the same family. For switches the names should be identical except for the addition of the word NOT to one of them.
[Warning: bad code ahead]
01 ACCT-NR PIC X(04).
88 ACCT-NR-RECEIVABLES VALUES '1000' THRU '1999'.
88 ACCT-NR-PAYABLES VALUES '2000' THRU '2999'.
88 ACCT-NR-EXPENSE VALUES '3000' THRU '3999'.
88 ACCT-NR-CAPITAL VALUES '4000' THRU '4999'.
88 ACCT-NR-VALID VALUES '1000' THRU '4999'.
For numeric account numbers, the first four 88-levels may work just
fine. The last one, though, is unreliable. It will happily treat
'32W@' as a valid expense account. At a minimum, you should rename that
last 88-level to ACCT-NR-IN-RANGE, and supplement it with a numeric
test.
Better yet, create a separate ACCT-TYPE-FLAG, and perhaps a separate ACCT-NR-VALID-SW. To an accountant, account numbers are meaningful values. They are not arbitrary codes which the programmer may assign at will.
Whenever you're tempted to use a THRU clause to define an 88-level, think again. If it is meaningful to specify a range, the variable on which the 88-level is based is probably not a flag with arbitrary values, but real data with meaningful values (see next section).
A THRU clause might be appropriate if you have chosen flag values in such a way that a range is meaningful. For our INPUT-STATUS-FLAG example, we might add:
88 INPUT-FILE-OPEN VALUES 'B' THRU 'D'.
Consider the following fragment:
[Warning: bad code ahead]
01 BALANCE-DUE PIC S9(5).99.
88 ZERO-BALANCE VALUE ZERO.
The value of BALANCE-DUE is not arbitrary. It's real money. The fact
that one possible value has special significance should not tempt
you to use an 88-level for it. It's perfectly clear to code IF
BALANCE-DUE = ZERO. Anything else is needlessly obscure.
Likewise, it would be misleading to code SET ZERO-BALANCE TO TRUE. It looks like you're just setting a flag, rather than changing a real value. Code exactly what you mean: MOVE ZERO TO BALANCE-DUE. No one will mistake your meaning.