When the same code is duplicated in two or more separate branches of a conditional, it can make the code harder to understand, maintain, and can
potentially introduce bugs if one instance of the code is changed but others are not.
Having two WHEN
clauses in the same EVALUATE
statement or two branches in the same IF
structure with the
same implementation is at best duplicate code, and at worst a coding error.
IF X = 1
MOVE A TO B.
PERFORM SECTION1
ELSE
IF X > 10
PERFORM SECTION2
ELSE *> Noncompliant
MOVE A TO B.
PERFORM SECTION1
END-IF
END-IF.
EVALUATE X
WHEN 1
MOVE A TO B.
PERFORM SECTION1
WHEN 2
MOVE A TO C.
PERFORM SECTION2
WHEN 3 *> Noncompliant; duplicates WHEN 1's implementation
MOVE A TO B.
PERFORM SECTION1
END-EVALUATE.
If the same logic is truly needed for both instances, then:
- in an
IF
structure they should be combined
IF (X = 1) OR (X <= 10)
MOVE A TO B.
PERFORM SECTION1
ELSE
PERFORM SECTION2
END-IF.
- for an
EVALUATE
, one should fall through to the other
EVALUATE X
WHEN 1
WHEN 3
MOVE A TO B.
PERFORM SECTION1
WHEN 2
MOVE A TO C.
PERFORM SECTION2
END-EVALUATE.
Exceptions
Blocks in an IF
chain that contain a single line of code are ignored, as are blocks in a EVALUATE
statement that contain
a single line of code.
EVALUATE X
WHEN 1
PERFORM SECTION1
WHEN 2
PERFORM SECTION2
WHEN 3 *> no issue, usually this is done on purpose to increase the readability
PERFORM SECTION1
END-EVALUATE.
But this exception does not apply to IF
chains without ELSE
-s, or to EVALUATE
-s without WHEN
OTHER
clauses when all branches have the same single line of code. In case of IF
chains with ELSE
-s, or of
EVALUATE
-es with WHEN OTHER
clauses, rule S3923 raises a bug.
EVALUATE X
WHEN 1
PERFORM SECTION1
WHEN 3 *> Noncompliant, this might have been done on purpose but probably not
PERFORM SECTION1
END-EVALUATE.