USER ABC 19900213 ''Arnold Cameron'' OPS YES USER SJM 19801125 ''Steve Martin'' DBA NO USER THN 19850522 ''Tom Nelson'' TEK YES USER WJT 19860330 ''Bill Toner'' TEK YES
A numeric reference to this SGS is apt to be very unintuitve:
To understand this reference, you'd either need to memorize what the second field contains or you'd need to look at the USER SGSs to see what it contains. Even this might not be much help: It obviously contains a date but what kind of date (birthdate, hire date, user-id issue date)? This might not be much of an inconvience if you only had to do it once or twice, but in a large skeleton with many SGSs you'd be constantly flipping to the SGSs to try to figure out what's going on in the code. Comprehension would be slow.
We've seen that skeletons are much easier to read when references in square brackets are coded with symbolic rather than numeric references. This is because a symbolic reference can be meaningful, as in:
If you can read English, you can get most or all of the meaning from this reference.
Another reason for avoiding numeric references is the maintenance problem that would arise if you must add, delete or move fields within an SGS. Imagine that the hire date field is no longer needed. You'd like to get rid of it but doing so would cause what's now the third field to become the second field, the fourth to become the third, etc. You'd need to locate and change every reference to the third and following fields in USER SGS references in all your skeletons--a tedious and error-prone task.
At bottom, SGSs are referenced by position, i.e., numerically. Substituting a variable for a numeric constant doesn't really change the nature of an SGS reference as far as SSG is concerned (but it makes a great difference to human readers). SSG must substitute the variable's current value to satisfy a reference. For the USER SGS in the above example, the programmer must supply these values with statements like:
*SET USER_ID = 1 . constant *SET USER_HIRE_DATE = 2 . constant *SET USER_FULL_NAME = 3 . constant *SET USER_DEPT_CD = 4 . constant *SET USER_DLOC_FLG = 5 . constant
You could include these statements in the initialization code of every skeleton that references the USER SGS; you might even make this a *COPY procedure. But I suggest going even further. Include these definitions as metaSGSs in the same symbolic element:
RELATION USER 1 USER_ID . unique identifier RELATION USER 2 USER_HIRE_DATE . date employee was hired RELATION USER 3 USER_FULL_NAME . employee first and last name RELATION USER 4 USER_DEPT_CD . company-standard department code RELATION USER 5 USER_DLOC_FLG . SYS$*DLOC$ assignment allowed? (YES or NO) . USER ABC 19900213 ''Arnold Cameron'' OPS YES USER SJM 19801125 ''Steve Martin'' DBA NO USER THN 19850522 ''Tom Nelson'' TEK YES USER WJT 19860330 ''Bill Toner'' TEK YES
I call the RELATION SGS a metaSGS because it describes another SGS (i.e., the USER SGS in this case). You can read the first RELATION SGS above to be saying, "For SGS with label USER, field #1 will be referred to as USER_ID." A *COPY proc will emit the *SET directives to create the variables defined in the RELATION SGSs.
This technique of including RELATION SGSs in the same element as the SGSs they describe gives the SGSs a self-contained quality--they are comprehensible on their own terms, without forcing the reader to look at the skeletons that use them.