Do It Now!
August 13, 2014 Hey, Ted
In our RPG programs we protect input operations (CHAIN, READ, etc.) with an error-handling routine that notifies users of record locks. That is, the RecLock subroutine sends a break message to the locking user and displays a window with lock information to the requesting user. This logic is not working in one of our programs, and we can’t determine why. Can you help? –Kent I’m glad Kent wrote with this problem. It gives me an opportunity to write about a topic that has been on my mind for some time. But first, here’s a trivia question for you to think about. What is the best way to debug a program? (I’ll tell you the answer at the end of this article.) Back to Kent’s problem. His RPG source code looked something like this: C Unlock SomeFile C DoU Not %Error C SomeKey Chain(E) SomeFile C If %Error C Exsr RecLock C EndIf C EndDo * . . . more stuff . . . C Update(E) SomeRec The update was failing due to a record lock. Yet there should not have been a record lock, because the CHAIN should have looped until the lock was gone. The problem turned out to be in the RecLock subroutine. Something caused %ERROR to return false, which stopped the do-until loop even though the record was locked. There is a valuable lesson here. I learned it in the mid-1980s, when I installed ASNA’s RPG III compiler on a System/34. (Remember those?) IBM shipped RPG II with the S/34. ASNA sold some enhancements that added such features as externally-described files and structured op codes (IFxx, DOWxx, etc.). In the box with the 8-inch diskettes (remember those?) was a book, and in that book was the lesson. Whoever wrote that book was wise. He (she?) recommended that the programmer either use an indicator immediately when it is set or save the indicator setting in an appropriate variable for later use. For example, not this: * ... omitted code * HiLoEq C CTYPE COMP 'E' 25 C N25 CTYPE COMP 'F' 25 C N25 CTYPE COMP 'R' 25 * ... more code C 25 EXSR EXPDT * ... more code C EXCPTDTLLIN * ... more code OREPORT E 1 01 DTLLIN * ... more code O 25 122 'EXPEDITE' But this: * ... omitted code * HiLoEq C CTYPE COMP 'E' 25 C N25 CTYPE COMP 'F' 25 C N25 CTYPE COMP 'R' 25 C MOVE '0' EXPFLG 1 C 25 MOVE '1' EXPFLG * ... more code C EXPFLG IFEQ '1' C EXSR EXPDT C END * ... more code C EXPFLG IFEQ '1' C MOVE 'EXPEDITE'MSG 8 C ELSE C MOVE ' 'MSG C END C EXCPTDTLLIN * ... more code OREPORT E 1 01 DTLLIN * ... more code O MSG 122 In the first code example, the programmer depends on indicator 25 to hold its setting so that it can be reliably used later in the calculation specs and also in the Output specs. This sort of thing works reliably most of the time, but occasionally something happens, often a program modification that unintentionally changes the setting of the indicator, and suddenly a program that has been working reliably goes haywire. In the second code example, reliance on the indicator has been removed. Indicator 25 is set once, and its setting is saved in the EXPFLG variable. Even if something else changes indicator 25, this program logic continues to work correctly. After I learned this technique, I typically used only one general-purpose indicator (other than screen-handling indicators) per program. “That’s all well and good,” I hear you say, “but I haven’t used an indicator in years.” To which I reply, “Wonderful! I’m glad you haven’t.” But Kent’s code shows that we can still make the same mistake in a more modern way. Built-in functions like %ERROR, %FOUND and %EOF are subject to the same error, even when a file name is attached as an argument. I suggested that Kent revise his code along these lines. D SomeFileError s n C DoU not SomeFileError C SomeKey Chain(E) SomeFile C Eval SomeFileError = %Error C If SomeFileError C Exsr RecLock C EndIf C EndDo Reliance on the %ERROR function is gone. Now, to answer that question. The best way to debug a program is to not put the bugs into the program in the first place. Best practices, even little ones like the lesson I learned from ASNA almost 30 years ago, reduce the introduction of bugs and promote reliable programming. –Ted
|