#EX1 – Natural, Adabas and JCL Code Conventions

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.


*      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)>
* <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)
* ______________________________________________________________________
* |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.


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.


Main logic indicator


* ----------------------------------------------------------------------

*  Main program                                                        

* ----------------------------------------------------------------------



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.


Subroutine content...


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.


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).


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.


/*> 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 messageJRA-123 JRA-234 JRA-345 #resolve
ResultResolves issues JRA-123, JRA-234 and JRA-345. Multiple issue keys must be separated by whitespace or commas.
Multiple commands on multiple issues
Commit messageJRA-123 JRA-234 JRA-345 #resolve #time 2d 5h #comment Task completed ahead of schedule
ResultLogs 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 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>
/** </p> </body>
/** :see MRNAMEC in DCOP.DEV.COBOL for the original</a>

Example Results:


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.


1 #CNT (I2)


Dynamic variables

zzz To be filled…


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…



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.

  • 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)
  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



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


    3 #NVM-IND (L)

    3 #DATE-TIME (T)





  ADD 1 TO #I



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

Job/member name and Jobcard
Job/member nameScheduled jobs: job name PRxxyyyy Scheduled jobs: member name same as jobname Adhoc jobs: job name PRxxyyyy Adhoc jobs: member name usually the program name
JobcardJob 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 blockStandard format including: Job/member, Function, Submitted by, Description (at least list steps), Change history
Step commenting & step naming
Step header commentingStandard format
Step nameseg. program name
Step CONDCOND on each step, or IF/ENDIF
Datasets (data datasets)
Dataset prefixesDxxD.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 typeUNIT=SYSDA, or UNIT=VTAPE Large datasets on VTAPE in production, otherwise on disk.
SpaceSPACE=(CYL,(n,n),RLSE) Tiny datasets use TRK instead of CYL. If very large, eg. hundred’s of cylinders, then use VTAPE.
Retention periodeg. RETPD=30/180 (days) Usually only for tape, including VTAPE.
Dataset deletion stepsUsually not in production
Job failure notificationUsually only in production.
Job okMay include: notify CSC, notify/email Border Systems Support, purge job output, delete Signal dataset, etc.
Job failedMay include: notify CSC, notify/email Border Systems Support, stop MQ triggering, etc.
Dataset library namesLoad libraries – AdaStrip: Load libraries – Adabas utilities: Parm library: DCOP.env.BATCH.PARAMS, PCOP.BATCH.PARAMS
LimitsAdaStrip OUTLIM, TIME on jobcard, record limits, etc.
Correct input datasets
Correct input parmseg. 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!