I'd use the EQUATE statements to create constants, and if you want to have them available to multiple programs you should place them in their own record and use the $INCLUDE statement to pull the definitions into other programs. Note that all of the values are going to be established at compile time.
As to "constants" that are established at some time other than compile time, or indirectly referencing values through tags (passing a constant reference), most U2 programmers use control records of some sort. Since the file system and the programming language in U2 are so intertwined, nobody ever thinks twice about this. Most systems I've used have one or more files called something like, "SOMETHING.OR.OTHER.CTRL" with free-form record structures. The editor is used to stuff data into records in the control file with keys that describe the function, like, "INVENTORY.CONSTANTS".
For indirect references, set up the record with the first attribute having the "constant" names multivalued and the second field with the "constant" values, also multivalued. Like this:
INVENTORY.CONSTANTS:
001: JOHN*PAUL*GEORGE*RINGO
001: 100*57*83*19833
(where the "*" is actually a value mark).
Then the program would do the following:
SUBROUTINE SAMPLE(CONSTANT.NAME)
.
.
.
OPEN "","SOMETHING.OR.OTHER.CONTROL" TO CTRL.FILE ELSE BOMB
READ CONST.REC FROM CTRL.FILE, "INVENTORY.CONTSTANTS" THEN
LOCATE CONSTANT.NAME IN CONST.REC<1> SETTING CONST.POS THEN
CONST.VALUE = CONST.REC<2,CONST.POS>
END ELSE
BOMB
END
END ELSE
BOMB
END