2

I am trying to come up with a good approach to handle errors in an RPGLE program with a number of SubProcedures.

dcl-proc getWorkKeyString;

   dcl-pi *n ind ;
    workKeyArray likeDS(parentWorkKeyArray) dim(500);
    workKeyString like(ISWCDUPDS.IWKEY_ISWC);
   end-pi;

   index = 1;

   dow (index < 500);

      monitor;
        if ( workKeyArray(index).workKey <> 0);

                if (index > 1);
                    workKeyString = %Trim(workKeyString)  + '|';
                endif;
                workKeyString = %Trim(workKeyString) + %char(workKeyArray(index).workKey);

        endif;
      index = index + 1;
      on-error;
        return cFalse;
      endmon;

   enddo;

   return cTrue;
end-proc;

As you can see, I have enclosed the do while body in a monitor group. If some error comes up, a false is returned from the sub procedure to indicate error. But please let me know if this looks like a good approach.

jmarkmurphy
  • 11,030
  • 31
  • 59
Theju112
  • 185
  • 7
  • 2
    I would not do it like that. First you're monitoring exceptions that are not likely to happen in production I think. The most probable exception I see is having array passed not initialized, where workKey is not a valid numeric. But having just a false returned is not the good thing to do I think, it's hiding more than handlnig, this kind of exception must break. Second your return value is just a boolean, you can't differenciate between exception happened and no workKey <> 0 found or any reason a procedure would say error. – nfgl Oct 05 '22 at 08:43

2 Answers2

4

One of the wonderful things about the IBM i is that it's generally exception-based rather than return-code based.

By monitoring for all exceptions and returning an indicator, you are creating a return-code based system.

With a return-code based system, you have to code like this in every procedure:

rc = someProc();
if rc > 0 
   ... return rc
else
  ... continue with the work
endif
rc = someOtherproc();
if rc > 0
   ... return error
else
   ... continue with the work
endif

It's very easy to forget to check the return code:

rc = someProc();
rc = someOtherproc(); // What if someProc failed?!

It's also very easy not to even bother getting the return code:

someProc();
someOtherproc(); // What if someProc failed?!

With an exception-based system, if I have some way of handling the error:

monitor;
   someProc();
   someOtherproc();
on-error;
   ... handle the error
   ... I could even use SND-MSG *ESCAPE to raise a new exception
       after I handle the error
endmon;

If I want to let my caller (or its caller) handle the exception, I can just let my procedure end when it gets the exception, and let the exception percolate:

someProc();
someOtherproc();
Barbara Morris
  • 3,195
  • 8
  • 10
  • 2
    I wrote a blog post in the RPG Cafe about this a long time ago: https://www.ibm.com/support/pages/node/1119309 – Barbara Morris Oct 05 '22 at 20:03
  • Hi @barbara, I agree with you. However the current code base that I am working with follows an approach where the results of the "business logic" processing done in a procedure is stored in the parameters passed to it and the actual return value from the procedure is boolean true if the processing completed without errors and the is boolean false, if some errors were encountered. As you said, I was previously used to an approach where the return value of a procedure is the output from the processing. I guess, the approach that I seeing now, makes more easier to return multiple return values. – Theju112 Oct 05 '22 at 20:20
  • great point about the advantage of exceptions vs return codes. Would be very useful if there was a switch that enabled DB2 SQL to throw exceptions instead of writing silent return codes to the joblog. – RockBoro Oct 06 '22 at 12:34
  • 1
    @RockBoro, you can now (since 7.4 I think, but maybe 7.3 too) specify a procedure call for EXEC SQL WHENEVER. If you code EXEC SQL WHENEVER SQLERROR DO someproc(), then someproc() can send an exception. The easy way for someproc() to send the exception now is with SND-MSG *ESCAPE. https://www.ibm.com/docs/en/i/7.4?topic=sql-handling-exception-conditions-whenever-statement – Barbara Morris Oct 06 '22 at 22:33
3

I considered closing this question as opinion based... error handling in RPG as with many languages isn't a one-size fits all.

I'd agree with the comment, your use of MONITOR doesn't seem very useful. Generally, you MONITOR for expected and handleable errors in such small sections of code.

I'd suggest taking a look at Chapter 7 - Exception and error handling in the Who Knew You Could Do That with RPG IV? Modern RPG for the Modern Programmer Redbook (aka the "RPG Wizzard" Redbook). I've always been a fan of the Throw/Catch/Percolate idea; which is described in the newest version of the "RPG Wizzard" Redbook linked above. Throw/Catch is even easier now with the Spring 2022 introduction of SND-MSG and ON-EXCP opcodes

One caveat to Throw/Catch is that exception handling in RPG, as with most (all?) other languages, is expensive;

Also Consider how IBM codes it's APIs.

Charles
  • 21,637
  • 1
  • 20
  • 44