XTRAN Example — Mine Code for Business Rule Conditions
Scenario — you want to find the Business Rules (BRs) in your code, perhaps to move them into a Business Rules Management System (BRMS). A key to such BRs is the conditions that determine when they are executed and what they do when executed. However, you know that not all "if" statements are part of BRs. Additionally, you want to find out whether such conditions (and therefore the BRs they are in) are scattered throughout your code or centralized in subroutines.
What would really help would be a tally of how many times each condition occurs in your code. Such a tally should ignore the left side of a conditional operator in such a condition, because the BR is much more likely to be reflected in the condition itself, not a specific variable to which it is applied. And, if a condition is not a conditional operator expression (e.g. a condition name), then the tally should be of the entire condition.
XTRAN to the rescue!
The following example uses an XTRAN rules file comprising 110 non-comment lines of XTRAN's rules language ("meta-code") to mine COBOL code for control flow conditions and tally their occurrences as described above. The rules took one hour to create and debug. (That's right, only one hour)!
The rules output the condition tallies in the following format, one condition per line:
||is the condition|
|| is the condition's value, or
||is the condition's number of occurrences|
The XTRAN rules used for this example are not specific to COBOL; they can be used unchanged to mine any 3GL language for BR conditions.
Here is an English paraphrase of the XTRAN rules:
Open output file named by an environment variable; create or append depending on another environment variable For each code statement If it isn't an "if" statement Ignore it If its condition is an operator expression Grab operator as condition, plus its right hand (or only) term as condition's value Else (not operator expression) Use entire expression as condition, with "(none)" as condition's value Add condition to list of those we've seen Increment condition/value's tally (direct data base update) For each condition we saw For each value seen on this condition Output condition, value, and tally (direct data base fetch) Close output file
How can such powerful and generalized code mining be automated in only one hour and only 110 code lines of XTRAN rules? Because there is so much capability already available as part of XTRAN's rules language. These rules take advantage of the following functionality:
- Text file input and output
- Text manipulation
- Text formatting
- Delimited list manipulation
- Environment variable manipulation
- Content-addressable data bases
- "Per statement" recursive iterator
- Access to XTRAN's Internal Representation (XIR)
- XIR's language-independent properties
- Navigation in XIR
- Delayed / forced rules evaluation
The input to and output from XTRAN are untouched.
Here is a flowchart for this process, in which the elements are color coded:
- BLUE for XTRAN versions (runnable programs)
- ORANGE for XTRAN rules (text files)
- RED for
- PURPLE for text data files
Input to XTRAN:
IDENTIFICATION DIVISION. PROGRAM-ID. PROG. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT OUTPUT-FILE ASSIGN TO OPFILE. DATA DIVISION. FILE SECTION. FD OUTPUT-FILE LABEL RECORDS ARE STANDARD RECORDING F. 01 REPORT-REC PIC X(132). WORKING-STORAGE SECTION. 01 VAR1 PIC X(08) VALUE 'VAR1'. 01 VAR2 PIC 9(4). 01 CTR1 PIC S9(09) COMP VALUE ZERO. 88 CTR1-0 VALUE 0. 01 CTR2 PIC S9(09) COMP VALUE ZERO. 01 CTR3 PIC S9(09) COMP VALUE ZERO. 01 MAX PIC 9(03) COMP VALUE 100. 01 TBL PIC X(08) VALUE 'TABLE'. PROCEDURE DIVISION. IF CTR1 > MAX THEN STOP RUN END-IF. IF CTR1 = ZERO THEN MOVE 1 TO CTR2 END-IF. MOVE 500 TO CTR3. IF CTR2 >= 500 THEN STOP RUN. IF CTR3 = ZERO THEN IF CTR2 <= 5 THEN MOVE 6 TO CTR2 IF CTR1 <= 5 THEN MOVE 6 TO CTR1 END-IF IF CTR1-0 THEN ADD 2 TO CTR1 END-IF END-IF IF CTR2 > MAX THEN SUBTRACT 1 FROM CTR2 END-IF END-IF. STOP RUN.
Output from XTRAN:
<=,5,2 =,ZERO,2 >,MAX,2 >=,500,1 CTR1-0,(none),1