Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Specific: 77 level, use it or not!?!

Status
Not open for further replies.

wahlers

Programmer
May 13, 2004
142
0
0
NL

I myself am not a great advert of using 77 level data definitions.
It cannot be re-defined, renamed or grouped.
But sometimes these are exactly the characteristics that you want!

Example:

Program A calls B, B calls C, C calls D,
D calls...ad infinitum

Suppose an exception occurs in program 'D'.
What was the cause?
The cause might originate in program 'A', or any where in between!
Than how are you supposed to know?
[that is, traverse your way down (or up) the call chain]
And return some usefull info to whatever initiated this chain of calls?

My solution:
I pass the program 'identifier' [user defined within each program!]
and 'store' this identifier in a field in the called program:
Code:
PROGRAM-ID. programC.
 
77  saveCallerID  PIC  X(100).

MOVE  callerIDpassedInLinkage
  TO saveCallerID
.
.
* later some other program(s), programD,
* might be called.
* programD, in turn, might call 'E', 
* 'E', in turn, might call 'F', etc.
CALL programD  USING ...
.  
.
IF  someConditionOccured
  CALL  logTheSavedCallerID
  USING saveCallerID someOtherData
END-IF

* ...as each previous program will do 
* the same, thus effectively returning
* the chain of calls [the stack].
* which can than be logically and automatically
* processed by any program higher up in 
* the call hierarchy
Note: This is a simplification of the logic!
In reality the procedure is more complex!

Notice that the 77-level callerID is never used unless an exception occurs, and even then it is merely passed to be written to some log without interest to the contents of this field.
I never want this field to be addressed, sub devided or being overwritten.

I hope this example, and (defendable) usage of a 77-level field, was clear enough.

Any comments on the [usage of] 77-level!?!
pro/con's? Use it or not!?!


Regards, Wim Ahlers.
 
Wim -

Certainly food for thought.

I stopped using 77-levels many years ago as I couldn't come up with any substantive arguments for their continued use. I also ran into at least one restriction on their use:

IIRC, this was on HP's MPE compiler many years ago. 77-levels are not necessarily aligned (one of the reasons for their existence I suspect). Arguments passed to called routines had to be word-aligned, so (some?) 77-levels could not be passed as arguments to called programs.

If you change your 77-level to 01, are there any repercussions?

I also note you say it cannot be overwritten. That's not the case, it's modifiable just like any other field.

Regards.

Glenn
 
Glenn

When I said "it cannot be overwritten" I meant it is not allowed to be modified by some creative programmer!

And this is exactly why I favor the 77-level definition in this case!

Because it is a hell of a lot easier to code a small routine that automatically verifies [and refuses!] creative programs that move anything to this field than to verify any possible REDEFINE from, or addition to, a 01-level [or any other level for that matter]!

It is important that the value of this 77-level field is 'written' and 'read' by the responsible routine only.
The call functionality looks like this:
Code:
WORKING-STORAGE SECTION.
 
77  saveCallerID  PIC  X(100).

LINKAGE SECTION.

01  someUserData            PIC  X(01).
01  controlData.
  05  callerID              PIC  X(100).
  05  someOtherControlData  PIC X(..).

PROCEDURE DIVISION USING  someUserData
                          controlData.
begin.

* next call MUST BE first line after procedure!
* checked by automatic source verification
* routine BEFORE the source is even allowed
* to be compiled!
CALL  registerCallerID  USING  
      [input=]controlData [output=]saveCallerID


  [do whatever this program is supposed to do]


* next call MUST BE last line just before
* the GOBACK! [single exit point of course!]
* checked by automatic source verification
* routine BEFORE the source is even allowed
* to be compiled!
CALL  returnCallerID  USING  
      [input=]saveCallerID [output=]controlData 

GOBACK.
Again, the code is simplified!
The automatic source verification contains some
business independent integrity rules that all
programmers must obey [in this case forced!].

Using a 01-level [or any other level] other than 77 greatly complicates the verification tool [routine].
(checking now is easy...using the 77-level definition).

Having said this, there might be other objections against the 77-level definition [e.g. to become obsolete? Or not?].

I was aware of the non-allignment of the 77 level fields but this is not a problem because the only operation performed on this field are MOVE statements from alphanumeric to alphanumeric field.
AND only the controlling routine is allowed to do these MOVE!

Again, there might be other objections against the usage of a 77-level field.

Therefore, despite the 77-level being non grata, any objection that I might have overlooked!?!

I appreciate all personal experiences [and potential horror stories] that other people may have encountered.


Regards, Wim Ahlers.
 
Forgot to tell!
Any mis allignment is taken care of by the routine!
[redundancy check!]
 
I use 77 levels for constants where the syntax prohibits 78 levels. Other rhan that, there is no difference between 77 levels and 01 levels, other than the using groups. In most compilers, 77 levels are aligned. I think that is a COBOL standard rule, but of course any particular complier may violate any particular rule unless it is certified.
 
Webrabbit said:
I use 77 levels for constants where the syntax prohibits 78 levels. Other rhan that, there is no difference between 77 levels and 01 levels, other than the using groups. In most compilers, 77 levels are aligned. I think that is a COBOL standard rule, but of course any particular complier may violate any particular rule unless it is certified.

Unfortunaly it does! ...sometimes...
In my specific case it does not matter.
How and why is not important here.
But you are right! 01 and 77 should both be aligned.
See, among other:
And I quote this source:
Synchronized Data Items.
All level 01, 77 and SYNCHRONIZED data
items are aligned

non-alignment might (and does) give problems communicating (particular numeric) data between two different program languages (this on top of potential format problems).

Anyway...
You don't seem to share the majority of programmers
(at least I have the feeling it is the majority)
who consider the 77-level a "No-No" option.

As I said in the original post, I am not a fan myself because of the inflexibility of the 77-level. But in my particular case this inflexibility is an asset!

But I do like to hear experiences/arguments/horror-stories thus other reasons for objecting the 77-level!
...if there are any...


Regards, Wim.
 
So much depends on the machine architecture, the compiler, and the level of compiler optimization requested, but...

In general one should consider that 01 level items are called records for a reason. In most cases everything in them will be implemented as field offsets in an array, resulting in hardware indexing overhead every time they are used.

Working-Storage records are not meant as a source-level organizational convenience for the programmer. For example anything used as an index/subscript that will see heavy use should probably be a 77. Any "switches." Any accumulated results (which probably ought to be some form of native binary COMP-nn usage).

Most strings (DISPLAY items) probably don't suffer much from being globbed into an 01 though.

But once again there are lots of variables involved, the biggest one being how your program uses the various Working-Storage items you define. And there are more important no-no's in Cobol from a performance perspective, like clearing records to SPACES within loops when they don't need to be cleared, etc. (there's a long list I suppose we're all aware of).
 
Dilettante,

Thanks for your constructive input.
But I think we are discussing two different issues here!

First of all...as a (personal) rule...I define (in almost all cases) all my workfields in just one 01-level definition.

In my experience I have found it valuable to have these workfields in one contigious space area (easy to spot in dumps, easy within test tools, or simply test 'DISPLAY' statements, and the like...).
To me the (internal) offset within 01-level record definitions has never been an issue that I was able to measure being a bottleneck!

But that is not the issue!
The issue was stated in my first (starting) post, and I quote:
Notice that the 77-level callerID is never used unless an exception occurs, and even then it is merely passed to be written to some log without interest to the contents of this field.
I never want this field to be addressed, sub devided or being overwritten.

I hope this example, and (defendable) usage of a 77-level field, was clear enough.
It is therefore not a technical issue, but a (logical) design issue!

Note: Later I remarked that I have a (sort of) scanning tool that scans all sources for certain design constructs (mandatory or forbidden - think 'GO TO'!) .
Reason: An attempt to prevent once written code to become spagetti code over time! I indeed restrict (on a certain level!) the programmers creativity!
And that is the issue at hand!

Following is off topic!...

Question:
Did you ever measure a noticable performance degradation
Between using:
Code:
01  a-whole-bunch-of-fields.
  05  field1
  05  field2
  05  ...
  05  FieldZillionth
AND:
Code:
* a-whole-bunch-of-fields.
  01  field1          *> 01 can also be 77
  01  field2
  01  ...
  01  FieldZillionth
I am just curious!
I never experienced this in the mainframe environment I used to be used too!


Regards, Wim Ahlers.
 
Some days it pays to keep my mouth shut. Yesterday was clearly one of those days. ;-)

I'm backing off because I've been down this road too many times over almost 30 years. I know better than to discuss style when it comes to any programming language.

I laud your efforts to work toward cleaner and more readable source code though.
 
Dilettante

Maybe I expressed myself poorly!
By no means was it my intention to criticize your 'style' or even suggest my 'style'.

On the contrary!
You actually provided a valid reason to use 77-level parameters (more efficient in heavy duty loops!).

As you no doubt have experienced yourself (in the past, present and future) COBOL programs tend to be adapted many times over re-using (or abusing) filler fields and re-using/redefine (or abusing) record structures all but destroying the most well intended original design.

You may consider 'restricting' the usage of certain COBOL constructs as 'style'...and I can go along with that!
But I actually don't care if the code itself uses postfix- or prefix- tags, other naming conventions, alignment conventions and the like.

I have the impression that you are tired of discussing these kind of issues...and indeed they usually are fruitless.
Even though we should program ego-less we all have our ego-s...myself included!

Therefore, let me rephrase the original question into a more general question:
Have you, with your years of experience, found an adequate technique that contributes into protecting the design (any design!) against creative abuse?
With the purpose and intent to stimulate (reliable!) re-use of (coded) functionality?
In other words: It is exactly your experience I am interested in. So, I can broaden my horizons (note: As I have the moral obligation to return my experiences. I don't want to be a paria! See (among others): and and
Some remarks:

1. I know that, in the end, there never is protection against creative programming abuse.
2. I know that, this general question sounds like a 'please_solve_my_problem' question.
3. I do have a couple of (mainframe) experience years myself (about 14 years).
4. The 'technique' I am using myself is a kind of pre-compiler that consists of two distinct functions, namely:
a) automatically generate functional program documentation, and,
b) refuse certain program constructs (e.g. the use of 'GO (TO)', the use of sections [note: which are indeed 'style' issues but I am agnostic to the fact if somebody else uses these kind of constructs or not!]).
5. I personally never program/optimize for speed. I start optimizing only when there is a incentive to do so (e.g. measured unacceptable response times. But, of course, I am aware of, and do use, certain obvious techniques such as lazy initialization, structuring evaluate statements in a decending frequency order [when known!], limit (working-)storage resources, balance by-content and by-value issues, etc...as we all do...!)

Note: English is not my native language (I am Dutch). I apologize upfront for any grammatic errors or, more importantly, any semantic misunderstandings.


Regards, Wim Ahlers.
 
Your English is very good and I have not seen language as an obstacle here. I only wish my Dutch were passable even for emergency tourist use. Alas, a self-teaching primer in Dutch has been sitting here at my left hand for almost 2 years and I haven't finished it yet.

I really do appreciate your sincerity. Producing and maintaining legible programs is very important. The problem domains in which Cobol is used seem to lead to software with very extended lifetimes. This makes long-term maintainability more important than for some other programming languages.


I do not consider myself a Cobol programmer. Today it is about 5th or 6th in a list of programming languages that I use.

In answer your question about protecting program design and promoting reuse I believe Cobol-85 introduced something that Cobol sorely lacked for 25 years: true modularity. The ability to have actual parameterized procedures with local-scape data should have gone a long way toward improving Cobol programs in the way you describe.

Sadly, many people are still using Cobol-74, some "halfway" 74/85 hybrid, or even with a full Cobol-85 (or later) compiler still write code as if they were using Cobol-68!

Some of this is due to conservatism. A good deal more may be due to the generally horrid nature of Cobol syntax itself. The necessary extensions to make Cobol-85 support parameterized procedures with local data have even scared off Cobol programmers.

Regarding data declarations and level numbers, the Cobol spec is pretty clear. Scalar items are supposed to be 77s and 01s are meant to group fields and/or groups of fields into records. Nothing else.

Thus using 01s to group "related" scalar data is an abomination. One which the compiler will punish you for at runtime with diminished performance and possibly even unanticipated side-effects. Doing this will undermine almost any compiler's attempts to produce optimized code.

Some may choose to accept these tradeoffs.

...then I get called in when their simple programs take over 10 hours to execute. I make a few (mostly trivial) changes and we reduce runtime back to the 15 minute range.

One of the first things I do is dismantle these "stylistic 01s" into 77s. Next I look for DISPLAY 77s and convert any that make sense into binary (COMP-xx) USAGE items.

Thirdly, I look for "Cobol Stupidisms" and eliminate them. These tend to consist of setting items to SPACES or ZEROS that either are already "cleared" or do not need to be because the next operation overwrites them anyway. Closely related are cases where a number of large 01s exist with a "record type" field. Lots of old programs load up these Working Storage records with input after clearing these long record areas to SPACES. Then after some processing they decide whether to write each record to the output file by comparing each whole record area against SPACES! I simply change the program to clear out the "record type" field of each record prior to input and test the "record type" for SPACE before output.

Only when this sort of silliness has been dealt with do I try to look at algorithmic inefficiency. One can almost always find plenty of that, but it takes lots of forms. Usually you can find a lot of loops that can terminate early but the programmer lets them trundle through to the end anyway. Sorting input that is given to the program already sorted is another common time waster. Stripping out gratuitous PERFORMs, ripping out pointless paragraph names, and otherwise unrolling Procedure Division code into straight-line logic saves a bunch as well.

Twelve weeks later I get called in again, to "repair" the same program once more after Joe Cobol has messed it up again. I document these things for Human Resources. Three such "strikes" and Joe Cobol is out pounding the pavement.

Peformance is about money.


"Structured Cobol" is a contradiction in terms. Despite the hue and cry this always raises, the fact is that the language is so horrid that attempts to impose "structure" on it are very costly at runtime.

The designers of Cobol were hack assembly language coders with no concept of control structures. They were used to GO TO-ing everywhere and even altering branch targets on the fly by modifying their program's code at runtime. They rejected the hard work published a year earlier by the Algol Committee, who did spend a great deal of time exploring program structure and produced a document that has influenced every procedural language we use today - except Cobol.

The compilers can't be blamed. The language allows really horrible and nasty things, like using a "paragraph name" as a:
[ul][li]Fall-through point (basically a comment).[/li]
[li]Target of a branch operation (GO TO).[/li]
[li]Target of a subroutine jump (PERFORM).[/li]
[li]Boundary marker for a subroutine jump (PERFORM THRU).[/li][/ul]
And all of these must be permitted at the same time because the spaghetti bowl that is a Cobol program is permitted to do any (or all) of these things, and make its decisions of which thing to do at runtime and make different decisions as it runs!

Ack! Ptui!

Thus every extraneous paragraph name costs your employer money, as does every 77 that you group up into an 01 for stylistic reasons.


Given all of this you might think I'd have welcomed the "Structured Cobol" movement when it came in, as well as ongoing efforts to create "Cobol With Style." After all, it sounds like a goldmine of job security for me.

The problem is that I have my own job to do, and unraveling the disasters caused by misguided attempts to stylize Cobol source is just more work I must pack into my workday (or worse yet get dragged in to handle, unpaid, on weekends).


Cobol is a valuable tool. Readable Cobol is important. But imposing source-level "style" on something as inherently primitive as Cobol syntax is frought with peril. I won't quote Edsger Dijkstra who once made a rather blunt statement to get peoples' attention, but he knew what he was talking about.


So as I said earlier, it is generally best that I bow out of this sort of discussion.
 
dilettante

This discussion veered of into another direction...but that is ok!

You seem to be a passionate analyst.
I say analyst and not programmer because I consider programming less important than the analysis itself.

This is my background (and passion!)...

In my experience I have found little (to none) code that is actually being re-used.
And re-using is something else than using!
An example of using is the ever famous date routine!
Every shop seem to have their own version and many shops even have multiple versions!
That is not re-use!

But you can only re-use functionality when it is stable (the code) and known (reliable, clear, easy-to-retrieve and up-to-date documentation) and has a well defined purpose (refactored function(ality)).

I like javadoc, even though crude, it does generate limited but reliable source information.
I worked on that idea and created a kind of 'coboldoc' or actually 'sourcedoc' because it is language independent!

But getting reliable documentation is not even half the story!

(correctly) Refactoring is another major part!
More so!...I consider this the hardest part!

And then of course these (hopefully!) well documented and (hopefully!) well factored functions should be protected (re-used as black boxes). For this I use a class-based approach (note: OO is not possible using COBOL85. I [still] use COBOL85).

In one of the projects I participated in we re-used functionality for both batch as well as event driven transactions.
And there are definitely some issues here!
For instance with event driven transactions you want to verify the input for every single transaction (to preserve data integrity).

But batch runs may consists of millions of pre-formatted, already verified, records being processed of which each record to be processed can be considered to be a single event!

It would be foolish, as you said in your own terms, to verify or initialize that which has already been verified and initialized!

Now, the class based system I worked on has some 'awareness' (state data!) and 'knows' whether it is batch or an online transaction. More so, it even auto-magically calls the correct polymorphic method coded as a contained program within a class-based program.

Programs of the class-based systems do contain very little if-then-else or evaluate constructs, very little switches, no abuse (=redefine) of record structures at all, not a single record contains an at-end filler, no unnecessary loops, all this because there is absolutely no need for it!

And at the same time it is extremely easy to re-use the functionality using a completely different interface with a completely different purpose!
It sounds impossible but it really isn't!

BUT

It's weakness is the programmer!
As is the case for all long-life software the code/system tends to deteriate from the ready-set-go moment!
And, again, this was the basis for my original question.

By the way...whenever I encounter a spagetti system I happily add the next bit of spagetti code!
As you said, and I quote you:
The problem is that I have my own job to do, and unraveling the disasters caused by misguided attempts to stylize Cobol source is just more work I must pack into my workday (or worse yet get dragged in to handle, unpaid, on weekends).
To which I only can add the comment:
And when you actually do invest the time to clean the code and you make the smallest mistake everybody will point the finger at you!

A thankless task indeed!

It either takes your free time ELSE you make mistakes.
Or worse still:
You may make mistakes DESPITE investing your free time!
A lose-lose situation indeed!

As for performance:

I could not care less if a batch run that can start after midnight and needs to be finished before 5 in the morning runs 30 minutes instead of 15 minutes when optimized.
Of course, it is a totally different ball game, when it runs 6 hours and needs to be finished in 5!
However, I rarely encountered this situation!
Quite the opposite!

In fact, but this was over 10 years ago, I optimized the complete nightly batch processing in such a way (parallel processing) that it finished around 3 in the night! And the night shift had nothing to do between 3 at night and 7 in the morning.

And I too am concerned about money!
But from a different perspective!
I put the emphasize on change!
A system should adapt (as seven of nine would say [wink] ) to the ever changing business rules reliably and within a practical timeframe!
And, in my humble opinion, this is where the money is!
(note: not for the creative programmer but for the business).

Many collegues that I know consider it an unnecessary burden to invest some time into (attempting) to create a re-usable system. And indeed, the initial effort is a greater burden on (mainly human) resources! But, eventually well worth the effort!

I enjoy to exchange viewpoints with you and I do hope not to burden you (...too much)!


Regards, Wim Ahlers.


Considering programmatic performance (in general) this is my often used answer:

"I can increase the performance of your system by about 5% by doing absolutely nothing!"
"That is...I observed that this is, on avarage, about the yearly standard performance gain due to standard hardware, software and network upgrades!
 
dilletante -

I too am leery of jumping into a religious war vis-a-vis style, etc.

In general, I agree that I find too many COBOL "stupidisms" in existing code. I am, however, interested in your assertion that combining scalar items into a single 01 incurs a performance penalty. I've coded on a number of platforms and have not found that to be the case. Can you provide specific examples of the COBOL compilers that produce such code?

Thanks,

Glenn
 
Whatever they say, COBOL has often a much better performance than many other languages like for example C or C++. Search on the web for COBVSC at CA's FTP site and enjoy.

Maintainability is about good behaviour of programmers. People should use a good development method like JSP. It is less import than which language to use to implement things.

As we say in Holland, C and C++ looks far too much like SM-bler.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top