My preferred entry macros use a workarea beginning with a save area, with standard labels for the SA part of the DSECT. They include COPY code for global SET symbols and a macro for parsing options out of SYSPARM. The eye catcher includes a timestamp.
There is spaghetti code without GOTO and there are clean programs that use GOTO.Branch labels still have legitimate uses. ObThanksGregMushial I use dependent and labelled USING to avoid clutter. I use *both* block comments and line comments; each has an important role. Saving storage is not a valid excuse for cryptic messages. -- Shmuel (Seymour J.) Metz http://mason.gmu.edu/~smetz3 ________________________________________ From: IBM Mainframe Discussion List [IBM-MAIN@LISTSERV.UA.EDU] on behalf of Rob Scott [rsc...@rocketsoftware.com] Sent: Wednesday, June 16, 2021 11:19 AM To: IBM-MAIN@LISTSERV.UA.EDU Subject: Re: Coding for the future My 2c (assembler bias). (1) Get yourself decent module and subroutine entry and exit macros that handle passing parameters and returning RC,RSN and output pointer. (1a) Don't use any register apart from R15, R0 and R1 to return info to caller. (1b) Too much logical nest indenting is nature's way of telling you that you need a new subroutine. (1c) Always think "can what I am writing be made into a generic function and used by other modules?" (2) Get yourself a decent internal trace routine - this is worth its weight in gold (3) No branch labels - use structured programming macros - no spaghetti (3a) Recovery points (and things like EODAD) are only exception to this rule, but are hidden from normal view under a macro specification (3b) Single entry + single exit from any subroutine or module (3c) FLOWASM - game changer (4) Long and descriptive variable names with namespace of the related structure followed by one or more separator chars (eg "_") (4a) Your DSA/working storage is a structure - use a standard name for it (I use "WA" and then "WA_FOO_BAR" etc ) (4b) Your constants (global or local) are part of a logical structure - use a standard name for it (I use "LC" for local constants and then "LC_FOO_BAR"). (4c) Global equates in a separate macro/copybook (5) Strict naming standards, especially for equates and bitmasks , for example for structure "FOOBAR", its length equate is always "FOOBAR@LEN" and for flag byte "FOOBAR_STATUS_FLAG", the bitmask equates would be something like "FOOBAR@STATUS_FLAG_ACTIVE" (5a) Using the above - I can code a macro that turns a bit on/off *without* having to know the name of the flag byte field (which eliminates a common hard-to-find problem where the a bit is turned on in the wrong flag byte) (6) Always DROP and re-establish USINGs when entering subroutines - hanging USINGs are very dangerous (6a) In my code this is done by module/subroutine prologue/epilog macros (7) Use reason codes with component IDs for the CSECT where the code was set (7a) RC = xx RSN=ccccyyyy (xx = RC, yyyy = RSN, cccc = component ID of CSECT that set "yyyy") (7b) RC+RSN can be surfaced many CSECTs above where originally set - really helps debug/trace efforts (8) Comment box and not lines (8a) Line comments get out of date with the source and copied around to the point of confusion (8b) Comment box above sequence of lines describes what they are doing and remains relevant (8c) Long variable names and naming standards help in making each line of code easier to follow -----Original Message----- From: IBM Mainframe Discussion List <IBM-MAIN@LISTSERV.UA.EDU> On Behalf Of Phil Smith III Sent: 16 June 2021 14:38 To: IBM-MAIN@LISTSERV.UA.EDU Subject: Re: Coding for the future EXTERNAL EMAIL A fun thread. Bob Bridges wrote, in part: >1) long-winded variable names I used to write almost exclusively in assembler, before long variable names, so I’ve found this one hard to break—but it’s definitely a good idea. I tend to cluster labels as much as possible: that is, in routine Banana, I’ll use labels BananaStart, BananaTop, and the like. (OK, I’m pretending that I use long labels here—more like BANANAST, BANANATP, etc., but I’m workin’ on it.) This helps avoid surprises at assembly time when some other fruit gets involved elsewhere in the program later. >2) comment your work...I'm more likely to use one-line comments on every other >line and a paragraph at the head of each section. I learned this the hard way almost 40 years ago. Back at UofW, we ran a local CMS mod on VM/SP for a couple of months over the summer, when usage was light and we could afford the cycles. It logged the name of every command run off the system Y-disk. Then we would look at that data (early analytics!) and look for candidates to move into the nucleus (shared memory). One afternoon I was looking at a local CP mod we had that would let an unprivileged user get several bits of info about another logged on user all at once as a set of bitflags, instead of having to issue and parse multiple commands. I wrote a bit of assembler to exercise it. No comments—not even register equates—since it was just a quick&dirty little program. Then I added a few bells and whistles. Then a few more… You can guess where this is going: that module got put on the system disk because someone else found it useful, and the next year when we ran our analysis, it was the most heavily used local bit of code on the system. By this point it was over 2KLOC. Still no comments, no register equates. Yes, that’s the point when I decided I’d better change jobs :) I have been religious about comments since then. As Charles notes, there’s a skill to commenting. I’ve found way too many experienced programmers who can’t seem to grok this, and who say “There’s no point in commenting every line, it’s obvious what it does”. They’re missing the point: the question isn’t WHAT it does, it’s WHY. That SR R2,R2 is clearing R2; we get that, and you’re right, it isn’t worth noting. WHY is it doing it? “Clear MVCL input length”, “Tell XYZ no florks are available”, are meaningful and useful. The z/VM source code is an example of commenting done right. The ratio of code to comments is probably below 1.0. This is a good thing. Gil added: > An account of how it does >what it does can also be useful, but that tends not to >change when the program itself does. I’ve seen this argument against commenting *at all*. I don’t buy it: not updating the comments means you’re only doing part of the job. If you change how it operates, you HAVE to fix the comments as part of that. >3) Don't assume system commands will work correctly Also theological purity, absolutely critical. I’ve long said: Application programmers worry about how it will work. System programmers worry about how it will fail. Corollary: don’t deliberately hide errors unless you also check them. In CMS, an unknown command returns a negative return code. I spent several days on a weird customer problem back at Sterling that I eventually diagnosed as a Rexx program that someone had put TRACE O in for no reason. If they’d left it alone as TRACE N, the unknown command that “couldn’t” fail would have been traced. Even better, of course, would have been if the code explicitly checked for that failure, but this example counts as someone deliberately suppressing useful information. Don’t be that guy (gal). >4) Allow arguments in any order Indeed. Positionals with meaning of course make sense in some cases, but *ix always irritates me that you can’t put the ‑whatever option after unflagged positional arguments. >5) Consistent indentation Don’t get me started…! On CMS, REXXFORM XEDIT is invaluable for indenting Rexx consistently. Nobody has ever converted it to work in ISPF, which is a shame. If someone’s interested, I’ll happily help; my ISPF macro skills are not up to the task, I’m afraid. REXXFORM not only indents, but (unsurprisingly) finds many basic syntax errors in the process, so it often saves debugging time as well. I’ve not done much Python programming, but the fact that indention is embedded in the language structure is interesting. OK, new items: 6) When you make changes to a program, ALWAYS examine the delta by hand. This is easier in CMS, where you’ll use XEDIT in update mode and can thus look at the resulting update deck, but compare utilities and source control systems provide this as well. Yet I see folks not doing it in too many cases, so some debugging display winds up getting committed, etc. Obvious exception: complete refactor (when did “rewrite” become “refactor”, and why?). 7) (I expect pushback on this one) Also learned from VM (and done to some extent in z/OS): name modules and entry points with a common prefix. This minimizes collisions and makes it clearer what’s doing what. If module ABCXYZ ABENDs, and you know that prefix ABC means program ABC, then you’re already ahead of the game, vs. having to figure out what program the FETCH module is part of. People claim that naming modules with “more descriptive names” is somehow magic; if they contain ONE function, maybe. Otherwise, the name is as likely to be confusing as helpful in my experience. CP contains a few thousand modules, with six-character names and three-character prefixes. Those three trailing characters can and do contain a lot of information, and the fact that HCPFRCVM is an entry point in HCPFRC means that when you want to look at HCPFRCVM, you don’t have to first search the source tree to find the code. It also means that all messages from HCPFRC are prefixed with that string, so, again, you know a lot before you even start. I cannot (and don’t care to) think about the time I’ve wasted grepping for function names or header file definitions in source code because people did not follow this simple, basic rule. Yes, it also means that DSECT or header files use a naming scheme, as do the entries in them: the HCPFRCBK defines the FRCBK, and the variables in it all start with FRC. Rigor, rigor, rigor. It saves lives.* ...phsiii *You save enough time across multiple people, you’ve net saved a life. ---------------------------------------------------------------------- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN ================================ Rocket Software, Inc. and subsidiaries ■ 77 Fourth Avenue, Waltham MA 02451 ■ Main Office Toll Free Number: +1 855.577.4323 Contact Customer Support: https://my.rocketsoftware.com/RocketCommunity/RCEmailSupport Unsubscribe from Marketing Messages/Manage Your Subscription Preferences - http://www.rocketsoftware.com/manage-your-email-preferences Privacy Policy - http://www.rocketsoftware.com/company/legal/privacy-policy ================================ This communication and any attachments may contain confidential information of Rocket Software, Inc. All unauthorized use, disclosure or distribution is prohibited. If you are not the intended recipient, please notify Rocket Software immediately and destroy all copies of this communication. Thank you. ---------------------------------------------------------------------- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN ---------------------------------------------------------------------- For IBM-MAIN subscribe / signoff / archive access instructions, send email to lists...@listserv.ua.edu with the message: INFO IBM-MAIN