Guidelines for the Micro Focus COBOL Programmer
Coding standards! A sure fire way to alienate half your development team overnight. Even the most amiable of developers will find it hard not to take it personally that you've outlawed one of their favorite coding constructs.
And it is perhaps one of the reasons why I couldn't find too many examples of team coding standards. But I did get something much better. Good advice.
A few of us here on the LinkedIn COBOL Group were recently discussing the virtues of coding standards, in particular a top 10 list of Dos and Don’ts provided by NASA, see here for the full conversation.
As the NASA guidance was very much skewed to C programmers writing for safety critical systems, I decided to get the views of our own COBOL developers here at Micro Focus. What follows is by no means a coding standard but rather general guidelines we’d recommend to any developer new to COBOL.
It’s worth noting the context in which most of our COBOL developers work here at Micro Focus. While our compiler and toolset supports much of the IBM Enterprise COBOL dialect and various mainframe subsystems such as CICS, most of the code our COBOL developers write is destined to run on distributed systems, not the mainframe. So much of the code we write uses the Micro Focus COBOL dialect. Some of the developers also write COBOL code for the .NET and/or the Java platform, so OO COBOL is fairly prevalent in these cases but for these guidelines, we focused our attention on regular procedural COBOL usage.
So, thought we’d share these with you. Hopefully some good advice here for the novice and veteran alike. Perhaps you have one you’d like to add to the list?
Now, throwing out a list of rules is a good way to get burned I would think. And while it’s easy to undermine any rule, and the NASA examples were an easy target in some areas, please keep in mind the spirit of the guidelines below.
1. We use perform single section not perform thru and not perform paragraph
Perform thru is an open invitation to spaghetti code. Discovering you have to fix up a program that contains overlapping perform ranges is rarely a good way to start the day coding.
We typically favour sections throughout the code and rarely use paragraphs which are usually only found in some relatively old modules.
2. Always explicitly terminate conditionals – use END-IF, END-READ, END-PERFORM, rather than just ‘.’ Period
A period terminates all statements regardless of nesting.
3. Don’t use next sentence
As we don’t use periods as terminators neither do we use next sentence which jumps to next sentence after current block of code that is terminated by period.
4. Only use periods to terminate an entire section
Periods aren’t needed after every statement. We think the code is more readable without them and the absence of periods helps when restructuring code.
5. For new code, we favour pre-defined types at 01 level for numeric fields - binary-long, binary-short - rather than using picture and usage clauses.
It can improve performance of native and managed code, ensuring alignment.
6. We use typedefs often as opposed to copy replacing
Makes declaring groups much more readable, great for sharing across modules.
We still use copy replacing and groups, that’s still a useful feature in the language but typedefs can be really helpful.
01 coords is typedef.
03 x binary-long.
03 y binary-long.
…
01 pos-a coords.
01 pos-b coords.
…
move 3 to x of pos-a
7. We use exit perform to break a loop early – we don’t use GOTO
We also used exit perform cycle to commence next iteration of loop
8. All code is written in lower case
Because there’s no need to shout, the code speaks for itself.
9. We code without a right-hand margin
Particularly helpful in managed code as it can help keep a single statement on one line. The SOURCEFORMAT(FIXED|FREE|VARIABLE) directive changes the compiler’s margin handling.
10. We use call prototypes for type safety in native code
Let the compiler do as much type checking as it can.
program-id “Module” is external.
linkage section.
01 a-field binary-short.
01 b-field pic x(10).
procedure division using by value a-field
by reference b-field.
end program.
…
*> this code will result in a compiler error
call “Module” using by reference a-field b-field c-field
11. Use meaningful data names
This has always been the recommendation but it’s amazing how often it is ignored.
With today’s IDEs which can suggest variable names from the program’s dictionary there’s no reason to use cryptic field names.
12. Be consistent with existing code base but don’t make the situation worse
Like many COBOL systems, a lot of the Micro Focus codebase has evolved over many, many years. And some of it would certainly have been written at a time when these guidelines would not have been observed. If we’re digging around in an old module, we might choose to tidy up some questionable code but if it ain’t broke… but on the other hand, we won’t exacerbate usage of certain constructs such as GOTO and ALTER.
13. Guidelines evolve
Our guidelines aren't set in stone, more like Play-Doh. That’s not an invitation to completely disregard good thinking and experience, it’s recognition that new tools and language support can help improve the way we write software and guidelines can be adapted.
1. the spaghetti code is better, the code with perform thru is more readable thanh perform the single section and even lighter at runtime .