You've created the masterpiece of all masterpieces. This is THE definition of GREAT programming, poise and pride. But then Q/A calls and says, "There's a problem. We're seeing some BAD things happen." WHAT!!! Now what do you do?
Unfortunately, you need to go back find the bugs wreaking havoc on your masterpiece. Here are some tips for debugging your programs and how to troubleshoot your programs as you're building them and avoid problems at the end.
When I program I don't try and type it all in one sitting. When I get to a good stopping point, I try to compile it -- just for grins. Now, I know all of the people a little older then me remember the days of being docked pay if you had to compile your programs more then twice, but those days have been gone for oh, 30 years or so. So DON'T worry about your supervisor complaining that you're wasting valuable CPU time on wasted compiles. If he's concerned, offer to pay back the CPU time, currently measured in cents.
Back to our program: I get this neat "where am I right now" snapshot from the compile. So when I'm close to a finished product, I've already worked through my dumb mistakes, typos and other not-so-smart errors, and I'm well on my way to debugging the bad things I'm trying to fix, such as logic issues or possibly general oversights.
When I'm ready to compile I use the option DBGVIEW(*LIST) (for ILE programs). It's all I need to get the job done to properly debug my programs without requiring the source code to be around. *LIST embeds the compile listing into the object produced by the compiler.
If you'd like to be on the safe side and compile with DBGVIEW(*ALL), don't feel badly. Your supervisor may request a payment for the extra storage used (again measured in cents).
In any case, the program should be run through the debugger FIRST to see what's up and to double check your logic. You can set up breakpoints IN THE CODE, go STEP BY STEP through the code, set up conditional debugging -- it's a beautiful thing. You'll see more of your significant others (or for some of you, your game boxes. :-) )
Now let's look at some debug etiquette. Lets add some "stuff" to your code to make your lives easier. (RPG programmers will appreciate this tip.) Place the following H spec in EVERY RPG program you write from now on and ANY you have problems with. (This is for RPG IV and above.)
I call this little babe "the Equalizer!" but in reality the OPTION(*SRCSTMT) thing embeds the SOURCE line numbers into your compile, so when you're debugging OR when you have a problem with the program that causes a hard ERROR that stops the program, it responds by saying "Problem in line 40155," which actually means something to your SOURCE CODE that compiled the object, NOT the printout of the compile that was deleted shortly after it was moved into the production server. Whew!
The second part -- *NODEBUGIO -- is a gentle reminder to the compiler to NOT MENTION every single field retrieved from the file while stepping through code. For both of those really cool settings, thank the people who attend the COMMON user conferences for insisting that they get created and implemented. People used to stand up during Sound Off and complain about the way Debug functioned, and IBM eventually listened.
Now back to our tip. I told you that DBGVIEW(*LIST) will give you enough so you can source-level debug your program. You get into the source-level debug by typing the following command:
STRDBG PGM(library/program) UPDPROD(*YES/*NO).
UPDPROD is fancy talk for Update Production Data. NOW -– when you create libraries using the CRTLIB command (NOT DIRECTORIES) on an AS/400, iSeries or i5 you'll see a parameter called TYPE, which can be *PROD or *TEST. That means YOU can declare if this library is a TEST library OR a PRODUCTION library. Go check -– see if your PROGRAMMER libraries are TYPE *TEST or *PROD. If they are *PROD, then debug will consider those libraries a PRODuction library, and the ONLY way to update the data (OR UPDPROD) is to say UPDPROD(*YES). If they aren't, the DEFAULT for this is *NO, which STOPS debugging dead from updating PRODuction data. (I can hear 2,000 or so professionals hitting their heads on this one.)
Anyway, type the command and hit ENTER and your source pops up (as long as the proper compile option is selected). The REAL source lines (from the source file) are listed to the left of the statements, and you can use F6 to set a break point. Or you can do as I do and hit F10 and step through EVERY line of the program. Hitting F10 will place the debug session in line-by-line mode and place you back at your command line. When the debugger first starts (like right after you type STRDBG), your program is NOT running, which is a VERY important point. If you're setting breakpoints, (and I'd set one for safety) hit F12 to get back to a command line. (Or, as mentioned earlier, you can get your program in line-by-line debug mode by hitting F10.) Once there, you're in DEBUG mode.
From there, initiate your program by calling it directly issuing the command that starts the program. Or if you NEED to -- for complex programs being called by other programs –- create a SMALL program that sets up your test and CALL the program that way. At a later point, you can revisit that program to see if the program is called and returns the fields to your desired completion. Typically that calling program is there to take care of "complex fields" being passed to the program or anything that is more than five minutes' work on the command line. (Remember, I'm the lazy programmer!)
Once a break point has been satisfied or you're in line-by-line mode where the program BREAKS on every line your source is displayed, you can place your cursor on the field and hit F11 to DISPLAY that variable during your debug session. This ALONE is 80% of my life in the debugging system. To end, while you're in the debugger hit F3. F12 will continue the program, and F10 will step the program until the next line is reached.
Debug helper commands
Use the following line commands as helper commands while in Debug:
- DSPMODSRC (Display Modual Source): This displays the program currently in the debugger. You can also set MORE breakpoints or display fields in their current state (don't hope for much!). In a later article I'll discuss how you can put in some crafty conditional breakpoints, where you see the REAL COOL power of debugger.
- ENDDBG: This ends the debugging session.
- STRISDB (Start Interactive Source Debugger: For CL programs, I'd use the STRISDB, which is still shipped with ALL AS/400s as of V4. ALL OPM programs are debugged FAR easier in this debugger than in more modern RPG IV programs.
This tip by no means covers everything involved with debugging programs. In fact, it barely scratches the surface. Let me know if you want more details, and next month I'll give you some more tips.
Until then, this is the Lazy Coder signing off. Remember: Take naps once in a while!
About the author: Andrew Borts is webmaster at United Auto Insurance Group in North Miami, Fla. He is often a frequent speaker at COMMON and is past president of The Southern National Users Group, an iSeries-AS/400 user group based in Deerfield Beach, Fla.
This was first published in May 2004