Code Conventions
“Why would I want to write things elegantly when it makes perfect sense to me?” – One of my early mentors…
This page defines appropriate code conventions, standards and techniques for Natural Development. (This code and syntax is subject to review).
Code review should ensure all aspects adhere to the teams approved (and enforced) methods.
Zzz – If you see this, it means it will be updated (on my never ending to do list).
Zzz – Table of Contents
Code Structure
All code structure by default should not exceed 72 chars in width (though with the Mainframe Editor decommission and Natural One, this no longer really needs to apply).
Program header comment block
The program header block should be consistent across applications to ensure appropriate program description.
Example:
************************************************************************
* SYSTEM: <SYSTEM> (eg.123,ABC) - <system> (eg.Library CO)
* OBJECT: xxxxxxxx (Module Name)
* FUNCTION: <one line title> (eg.SYSTEM Emission check)
* CALLED BY: <program name(s) or JCL member(s)>
* DESCRIPTION:
* <1-n lines of description and notes>
* (eg. Example Return codes
* 0 code exists and is valid
* 1 table exists but outside of supplied date range
* 2 code exists but outside of date range)
*
* VERSION HISTORY:
* ______________________________________________________________________
* |Vers|Driver|Date |JIRA ID |Description
* |----|------|----------|-----------|----------------------------------
* |1.00|HERO01|2015/05/12|TCTTSS-1234|Test Web service compatibility
* |1.03|HERO01|2015/06/12|TCTTSS-2000|Test Web service compatibility
* |2.00|HERO01|2020/01/01|TCTTSS-5678|Test Web service compatibility 2
* |2.10|HERO01|2020/01/01|TWEB-123 |Test Web service compatibility 2
*
************************************************************************
Aligning variables / general comments (readability)
When editing code, a struct command is essential to line up code for readability (ctrl+alt+s) Natural One.
Tabs are the preferred option for deliberate spacing in natural code.
Additionally, complicated variables should also have clear descriptions lined up in comments.
Example:
Variable declaration

Field Assignment

Start & End of Program
The main contents of a program should be identified immediately after the initial header block to indicate mainline processing.
The end of the program should always have an empty line after END.
Example:
Main logic indicator
* * ---------------------------------------------------------------------- * Main program * ---------------------------------------------------------------------- * End

Start & End of Subroutine
Subroutines should be used to dissect code into maintainable chunks and decrease the overall cyclic redundancy.
Subroutines definitions should span the entire width of a standard natural module (78 chars).
Clear indication of the “DEFINE” and “END-SUBROUTINE” is essential for readability.
What also is a nice touch is adding the subroutine name in an inline comment.
Example:
**----------------------------------------------------------------------
DEFINE SUBROUTINE GET-CACHE
**----------------------------------------------------------------------
*
Subroutine content...
*
END-SUBROUTINE /* GET-CACHE
*
Comments
References to JIRA / Efixes vs Traditional comments
Given JIRA is now our preferred method for ongoing development work, JIRA references provide a simple ID to encapsulate a large amount of data. The reference can be used to further interrogate the entire premise of a fix. These should be used for code changes in the first instance.
Small informal comments might still be necessary to indicate the intentions of complex code (e.g. “this hold variable required here to save looping”, “formatting a string to date”) which would be otherwise unrelated to a JIRA task/efix.
One thing to keep in mind too, with “Smart Commits” (where the JIRA ID is stored alongside a Git commit) commenting essentially becomes somewhat defunct, as the committed code change will align with the JIRA task. This is where it is crucial to include links to JIRA and formal well written commit messages to indicate the extent of a change.
Example:
Notice the JIRA Task has our Git repository for Natural with code commits along side it. The commit indicates new parameter data areas were ‘added’ and the commit message takes the place of comments littered throughout the modules.

In Line Comments
In line comments should directly relate to a changed piece of code as a key indicator.
Blank line comments can commence with simply *.
They should be short & succinct, (direct to a reference).
Example:
RESET INITIAL #MSG(*) /* Clear out the log information to display info
LETS-DO-THE-TIMEWARP /* TWEB-1222 (Example of a JIRA reference)
* Example of one liner, in timer of codes lines below…
Spanning comments
Generally used to indicate a vast span of code in natural which is injected and relating to a change.
Again should follow the principles of In line comments.
Indicated with the greater than and less than symbols.
Example:
/*> TWEB-1222
/*< TWEB-1222
*> Start of trialing more efficient code
*< End of the trial
GIT Commit Messages (Smart JIRA References)
“What’s the big deal with smart references? They’re not so smart”. Wrong.
They link everything into a big beautiful map, all with a simple reference (and should be used religiously where ever relevant). Your ‘commited’ code, will magically appear in all references (and most importantly the issue).
Simply reference in commits for most affect: https://confluence.atlassian.com/fisheye/using-smart-commits-960155400.html
Now we DO have commit templates, but even if not using these, you should ensure you have a reference to the Issues you are resolving in your natural code and your commit message.
Here is an example of the SYSTEMNat template (which is stored in the base of the project. The person committing their code simply remove the tags not required to ensure an informative and clear message alongside their commit.:
Example Template (SYSTEM.gitmessage.txt):
TWEB/TCTTSS- : Subject line (keep below 50 chars) (see examples)
# Lines starting with ‘#’ will be ignored. Replace details below.
#
Detailed description of change. Be as detailed as you want and may span
over many lines. It is advisable to limit line length to 72 chars.
# Additional optional tag specific information
#
# JIRA-ISSUE-TAG #comment Why is this change required?
# JIRA-ISSUE-TAG #comment How does this change address the issue?
# JIRA-ISSUE-TAG #comment What are the side effects of the change?
# How long did the work in this commit take? 1d or 4h etc.
# JIRA-ISSUE-TAG #time 1w
# DO you need to change the Ticket status?
# JIRA-ISSUE-TAG #done|#in-progress
Example of other forms of Smart Commits:
A single command on multiple issues
Syntax | <ISSUE_KEY1> <ISSUE_KEY2> <ISSUE_KEY3> #<COMMAND> <optional COMMAND_ARGUMENTS> etc |
Commit message | JRA-123 JRA-234 JRA-345 #resolve |
Result | Resolves issues JRA-123, JRA-234 and JRA-345. Multiple issue keys must be separated by whitespace or commas. |
Multiple commands on multiple issues
Syntax | <ISSUE_KEY1> <ISSUE_KEY2> … <ISSUE_KEYn> #<COMMAND_1> <optional COMMAND_1_ARGUMENTS> #<COMMAND_2> <optional COMMAND_2_ARGUMENTS> … #<COMMAND_n> <optional COMMAND_n_ARGUMENTS> |
Commit message | JRA-123 JRA-234 JRA-345 #resolve #time 2d 5h #comment Task completed ahead of schedule |
Result | Logs 2 days and 5 hours of work against issues JRA-123, JRA-234 and JRA-345, adds the comment ‘Task completed ahead of schedule’ to all three issues, and resolves all three issues. Multiple issue keys must be separated by whitespace or commas. |
Result Example (for display by clicking commits):

This example is really nice as it shows the multitude of projects involved in a change, really handy as you cross languages, dialects, intelligence and frustrations.

Here you can see Natural Code (SYSTEMNat), Service Layer (SYSTEMSvc) and the Web front end (SYSTEMWeb) layer all intertwined in this!
Also for a quick synopsis of how your code is travelling, this is handy too:

NatDoc
NatDoc is a nice, little, “built in” for viewing code comments in a pretty
html based form… but the underlying factor is it must be bundled into your natural module, written to the correct syntax and generated as required.
You can generate it for all your modules, and it will create a nice html trail to trawl to your heart’s desire (you can then upload this generated html to a specific place for your teams viewing).
Personally though, I find tools like Natural Engineer or a quick command (ctrl+h – to find a string) much more effective for trawling than NatDoc documentation could produce. Saying that though, there is the opportunity to expand on well documented code and module implementation with this specific add on.
As stated, there are better tools for this documentation (and if you use smart commits with CORRECT information in your templates you’ll avoid the need for such robust documentation).
There is a Live “View” in NaturalOne to view this documentation (which, I will remind the reader intrinsically hidden in commented code with specific tagged references in Natural) to easily render the content in a readable form while editing / reviewing a module.
Example NatDoc:
/** MRNAME – Absorb and convert all MRNAME key generation functionality
/** from original COBOL and transform to Natural Code.
/** <h2>MRNAME Key generation Natural utility</h2>
/** :author Trentan Healey
/** :version
/** <table border=”1″ style=”width:100%”>
/** <tr>
/** <th>Number</th>
/** <th>Developer</th>
/** <th>Date</th>
/** <th>Action</th>
/** <th>Comment</th>
/** </tr>
/** <tr>
/** <td>1.00</td>
/** <td>Trentan Healey</td>
/** <td>02/02/2016</td>
/** <td>Enable Webservice</td>
/** <td>Initial Version, convert the COBOL to Natural</td>
/** </tr>
/** <tr>
/** <td>1.01</td>
/** <td>Simon Kneebone</td>
/** <td>16/05/2016</td>
/** <td>Enable Webservice</td>
/** <td>Finished creating</td>
/** </tr>
/** </table>
/**
/** <body>
/** <p><i>Module Comments:</i><br>
/** This program has been written to encode family-names,
/** given-names and year-of-birth of the user input to retrieve
/** records from a database with the key generated by this
/** program.
/** Family names are encoded first then one or more given
/** names if needed.
/** Year-of-birth is the last 2 characters of the key.
/** The End-key is also encoded as per section 1300.
/** initially this program is used to load the database with
/** the Name-keys generated by this program.
/** In a search blank input data will cause a blank start and
/** end key.
/** This program is split into several sections each of which
/** is independent of the other.
/** <br>
/**
/** Each expects <br> Temp-name : Name being encoded
/** <br> Name-length : Length of the encoded name <br>
/** These ‘parameters’ are passed into and out of each section
/** the section names are
/** <ul>
/** <li>100-Cics-interface.</li>
/** <li>300-REMOVE-ALL-BLANKS-ETC</li>
/** <li>400-PREFIX</li>
/** <li>600-SUFFIX</li>
/** <li>700-MIDDLES</li>
/** <li>800-REPEATED-CHARS</li>
/** <li>900-CHECK-FOR-VOWEL-ETC</li>
/** <li>1000-UNSTRING-NAME</li>
/** <li>1100-ENCODE-GIVEN-NAME</li>
/** <li>1200-YEAR-OF-BIRTH</li>
/** <li>1300-ENCODE-END-KEY</li>
/**</ul>
/** </p> </body>
/** :see MRNAMEC in DCOP.DEV.COBOL for the original</a>
Example Results:

Variables
Ensure proper definition, avoid field truncation and resource over-allocation
zzz To be filled…
Naming conventions
zzz To be filled…
Counters (I2/I4 is best)
Traditionally, most counters in Natural revolved around things like (P5) or (N4).
Counters should be clearly defined and the best instantiation of the variables is in an integer (I) form with respective sizing of their intentional applications theoretical maximum (I2 → short – max value = +/-32767 & I4 → int max value = +/-2147483648) .
Ensure they are named appropriately too (‘#I’ is not sufficient for long running transactions!).
This naming and variable definition is important for use in debug operations (which we all inevitably need to use at some stage). While ‘i’ is a common used form / variable name in many languages, perhaps it’s time for ‘i’ to move on and become something better.
Example:
1 #CNT (I2)
1 #TIME-TO-LIVE (I4)
Dynamic variables
zzz To be filled…
X-Arrays
zzz To be filled…
Full Definition when referring within modules to DDM/PDA/LDA/Labels
zzz To be filled…
Read / Find / Get
When should I use…
zzz To be filled…
Starting From/TO
zzz To be filled…
Labels (Instead of Line Numbers!)
zzz To be filled…
Update / Delete / Store
zzz To be filled…
End Transaction
zzz To be filled…
Sorting
Function
The SORT statement is used to perform a sort operation, sorting the records from all processing loops that are active when the SORT statement is executed.
SORT statements can only occur after END-ALL statements (which will close all preceding loops). You can sort by multiple sequential variables.
For the sort operation, Natural’s internal sort program is used. It is also possible to use another, external sort program.
Restrictions
- The SORT statement must be contained in the same object as the processing loops whose records it sorts.
- Nested SORT statements are not allowed.
- The total length of a record to be sorted must not exceed 10240 bytes.
- The number of sort criteria must not exceed 10.
Sorting with read/find
zzz To be filled…
Sorting an array
zzz To be filled…
Sorting a group array
There are two ways to skin that cat, decided whether you will really need two distinct arrays or are able to sort one group array with a placeholder variable.
Use a temp array (same size) and repopulate by using a variable count place holder to point to where to fill the final array from
1 #CH-ARR (1:*)
2 #ISN (I4)
2 #TS (T)
1 #CH-SORT-MAIN-ARR (1:*)
2 #ISN (I4)
2 #TS (T)
1 #CH-S (I4)
1 #CH-T (I4)
1 #CH-TS-HOLD (T) This simply becomes a placeholder for reference in the sort of two exactly the same arrays
RESET #CH-T #CH-S
#CH-EN := *OCC(#CH-SORT-MAIN-ARR)
RESIZE ARRAY #CH-ARR TO (1:#CH-EN)
FOR #CH-S = 1 TO #CH-EN
#CH-TS-HOLD := #CH-SORT-MAIN-ARR.#TS(#CH-S)
END-ALL
SORT BY #CH-TS-HOLD DESCENDING USING #CH-S
ADD 1 TO #CH-T
MOVE BY NAME #CH-SORT-MAIN-ARR(#CH-S) TO #CH-ARR(#CH-T)
END-SORT
Use the array with a long alpha place holder with the arrays group content defined the same
1 #MOVEMENTS (1:*) /* OUT 2 #NVM-IND (L) 2 #DATE-TIME (T) 1 #CURR-CNT (I2) 1 #I (I2) 1 #LOOP (I2) 1 #MOVEMENTS-HOLD /* notice as it is the same group name as above, the Natural sort needs reference data to fill back! #MOVEMENTS-HOLD-A in the SORT statement. 2 #MOVEMENTS-HOLD-A (A105) /* Needed for storage during array sort 2 REDEFINE #MOVEMENTS-HOLD-A 3 #NVM-IND (L) 3 #DATE-TIME (T) FOR #LOOP = 1 TO #CURR-CNT MOVE BY NAME #MOVEMENTS(#LOOP) TO #MOVEMENTS-HOLD END-ALL SORT BY #MOVEMENTS-HOLD.#DATE-TIME DESCENDING USING #LOOP #MOVEMENTS-HOLD-A ADD 1 TO #I MOVE BY NAME #MOVEMENTS-HOLD TO #MOVEMENTS(#I) END-SORT
Error/Trace/Log Messages
Error log messages (web based services)
zzz To be filled…
Adding trace messages
zzz To be filled…
Log messages
zzz To be filled…
Copycode example for messages
Force error
zzz *ERROR-NR :=
RPC calls: Don’t use Terminate, STOP, Fetch
Sending a generic email (COMAILN1 + COEMAILN)
zzz To be filled…
Using XMITIP in batch
zzz To be filled…
Copy Code / Subroutines
Refrain from code duplication
zzz To be filled…
NatStyle (Built in Natural One)
How to use Natstyle
zzz To be filled…
JCL checklist
Item | Notes |
---|---|
Job/member name and Jobcard | |
Job/member name | Scheduled jobs: job name PRxxyyyy Scheduled jobs: member name same as jobname Adhoc jobs: job name PRxxyyyy Adhoc jobs: member name usually the program name |
Jobcard | Job name as above, except job name prefix PR changes according to each non-production environment (DV, TS, II, IJ, IK, ST, TR) Job class as appropriate, usually P for production jobs ‘programmer name’ to describe job, eg. //PRMRR233 JOB ,’BIP F233 ANALYSIS’,CLASS=O,MSGCLASS=X TIME=1440 for very long running jobs NOTIFY=&SYSUID only if required/desired |
Job header comment | |
Header comment block | Standard format including: Job/member, Function, Submitted by, Description (at least list steps), Change history |
Step commenting & step naming | |
Step header commenting | Standard format |
Step names | eg. program name |
Step COND | COND on each step, or IF/ENDIF |
Datasets (data datasets) | |
Dataset prefixes | DxxD.env.* for non-production. PxxD.* for production. |
DCB (for each dataset) | DCB=(RECFM=VB,BLKSIZE=lrecl+4,LRECL=lrecl) DCB=(RECFM=FB,BLKSIZE=lrecl*m,LRECL=lrecl) Only specify DCB where necessary Use large block sizes for I/O efficiency Use BUFNO=32 for large Natural work files, eg. //CMWKF01 DD DSN=PMRD.MRXBRZP1.FILEnnn.R001.STRIP,DISP=OLD,DCB=(BUFNO=32) |
On each dataset allocation | |
Device type | UNIT=SYSDA, or UNIT=VTAPE Large datasets on VTAPE in production, otherwise on disk. |
Space | SPACE=(CYL,(n,n),RLSE) Tiny datasets use TRK instead of CYL. If very large, eg. hundred’s of cylinders, then use VTAPE. |
Retention period | eg. RETPD=30/180 (days) Usually only for tape, including VTAPE. |
Dataset deletion steps | Usually not in production |
Job failure notification | Usually only in production. |
Job ok | May include: notify CSC, notify/email Border Systems Support, purge job output, delete Signal dataset, etc. |
Job failed | May include: notify CSC, notify/email Border Systems Support, stop MQ triggering, etc. |
Other | |
Dataset library names | Load libraries – AdaStrip: Load libraries – Adabas utilities: Parm library: DCOP.env.BATCH.PARAMS, PCOP.BATCH.PARAMS |
DBIds | |
Limits | AdaStrip OUTLIM, TIME on jobcard, record limits, etc. |
Correct input datasets | |
Correct input parms | eg. in Natural sysin, ftp target |
Change any NATBAT41 to NATBATCH | |
Good practice | |
Please feel free to contact me or comment below to update this guide, request changes and add anything missed with other standards as required!