REALbasic University Resources:

RBU: Glossary Defines common REALbasic programming terms
  Archives Previously published columns
Translations: Dutch Courtesy of Floris van Sandwijk
  Japanese Courtesy of Kazuo Ishizuka
  Chinese Courtesy of Dong Li
  RBU Translation Guide Information on Translating RBU into other languages
Books: Matt's Book (2nd Edition!) Ideal for experienced programmers
  Erick's Book Best for beginning programmers
Websites: Mother Ship The publisher of REALbasic
  RB Webring Links to hundreds of REALbasic websites
  RESExcellence Another REALbasic programming column
  REALbasic Developer Magazine The premiere source for REALbasic instruction.

REALbasic University is Sponsored by

Make your Mac do what YOU want it to. Create games, utilities, cool Mac OS X tricks. Download REALbasic now and create your own software.


Print This Article

REALbasic University: Column 106

Debugging Part One

For the past few lessons we've been looking at progress bars, and I'd planned to move on with a look at a few more common problems and how to handle them in an OOP environment. But I recently had an experience that reminded me of the complexities of debugging, and I thought a brief series on how to debug would be in order.

Complex Interactions

When talking about cars and mechanical problems, I like to tell the story of my old Dodge. "First the heater went," I say, "then the air conditioner. I could handle those problems initially, but the air conditioner dying eventually killed the speakers, and I couldn't handle the road without music, so I had to buy a new car."

Of course that doesn't make much sense -- speakers have nothing to do with air conditioning -- so it's an intriguing statement and provokes a conversation. I usually like people to ponder this quandry for a few minutes, try to figure out what my air conditioner has to do with my speakers. To date, no one has been successful. They just think I'm nuts (which probably isn't far off the mark).

But when I explain, it seems painfully simple. You see, with the air conditioner out, I was forced to roll down my windows to keep cool. That meant a lot of wind noise, which meant I had to crank up the volume to hear the stereo. Eventually that blew out my speakers!

I tell this story to illustrate an important point about computers. What attracted me to programming is that it's logical: everything is ordered and works according to a predefined set of rules. But when you get into the world of debugging, it sometimes seems that order has gone out the window. Just like the air conditioner in my old car, seemingly unrelated events effect each other. Sometimes successful debugging requires thinking out of the box.

Now there are sophisticated tools to help you debug your programs, but the best tool is your mind. If you can train yourself to think like a computer, you can learn to see the sometimes hidden cause-and-effect that is producing the undesirable behavior in your program. Let's look at some examples.

The Debugging Process

There is no magical debugging progress. Debugging is complicated: every type of bug is different and needs a different kind of process to find it.

For example, the simplest type of bug is a syntax error: usually the compiler catches these when attempting to parse your source code. Here's one:

  
dim a as integer

a = 10,001

Obviously the comma is not allowed and REALbasic won't compile the application. But consider these examples that do compile but probably don't do what you want (assign the number 10,001 to a):

  
a = 10.001 // Result is 10, since a is an integer data type
a = 10+001 // Result is 11
a = 10'001 // Result is 10 since ' starts a comment

Syntax errors are usually typoes, but when the typo generates compilable code, it can be tricky to find the error. Usually the code produces unexpected results, which usually doesn't narrow the field much and help you figure out where the error is located.

But other errors are more deliberate. For example, it's a common technique to use simple variable names like i and j for temporarily variables used in loops and stuff. But i and j aren't particularly memorable, and it's easy to write a routine where you accidently use i where you meant to use j.

I just did this a few days ago in a program that processed folders and files you fed it. The outer loop was i, representing the number of folders. The inner loop was j, for each file in folder i. But the output was only showing a single file processed. I checked the input code and it was fine. That routine successfully read in a folder and all 27 items inside it. Yet the output had only one file in it! So where was the bug? I finally noticed that within my inner loop instead of refering to file j, I was referring to file i, and since i was a 1 (the first folder), only the first file was returned. A simple change and my program worked: but it took me a little bit to find the bug.

An easy fix to prevent this kind of error, of course, is to use more detailed variable names. If I'd used theFolderIndex and theFileIndex instead of i and j, I certainly wouldn't have made that error. Often when you're coding, though, it seems easier to use random letters for temporary variables instead of detailed names. Partly that's because your mind isn't completely clear on how the variables will be used so it's difficult think up an approrpriate name. Forcing yourself to create a detailed variable name will force yourself to think more about what you're going to be doing -- which will only help you.

Another common error happens when you copy and reuse bits of code. I'm lazy and rather than retype code, I'll copy it from a different section or another program. This can work and if the other code has been debugged, could produced more reliable code. However, you must watch out for variable names: you might have used different names in the original routine, or -- very bad -- used the same variable names but for different purposes. Fortunately, this type of error isn't as much of a problem with REALbasic because RB's auto-complete feature makes typing code in fresh so easy it isn't hardly worth copying.

Of course these are the simpler typo-type errors. There are many other kinds of errors you can make, and we'll look at some of those next time as we continuing to debug debugging.

Next Week

More debugging.

Letters

Today we've got a question from John about keycodes versus ASCII characters, among about fifty other puzzlers.

Dear Marc,

Sorry to keep bothering you, but I have some more questions/problems. This one started when I thought about modifying SuperDraw so that a selection made would deselect all other objects unless the shift key was down, indicating that you want a multiple selection. So I tried to find out what the ASCII character of the shift key was. I now realize that I don't need the ASCII character, since REALbasic, I discovered, has a built-in ability to test for the modifier keys. But other questions still remain.

In SuperDraw itself, there is 1) the problem of where to put the test. I thought of this addition when I was putting the code in the KeyDown event of drawCanvasClass which you include in the wrapup. But then I thought, well the KeyDown event is not sufficient, because most selecting is done with mouse clicks. So should I test in the MouseDown/MouseUp event?

Then I thought of another possible problem. I could make a guess at the probable answer in the old linear programming, but I am too new to OOP to understand the flow of events, and the carryover of information. In this case, the question is 2) if the shift key is not down, can you simply deselect all objects and then pass on the mouseclick, or will this cause the mouse click coordinates to be lost? i.e if the coordinates are still available, when the click (or press) is passed on, the object which is affected (withinMe) would see the mouse action and consider itself selected. But what would the effect be if the mouse action is within a selection handle, and you've removed the handle? Or would the selection handle have been redrawn when the action was passed on?

Finally in SuperDraw, while making one of your mentioned improvements, that the placeholder for a picture should not have a thick border if lineSize has been increased, it occured to me that lineSize appears to only allow a square pen. Is this correct? 3) Would I need to replace lineSize with two variables, vLineSize and hLineSize to allow complete freedom of the pen shape?

Going beyond SuperDraw, I remembered that you had uploaded a simple little program to display the ASCII keycodes. I found this, and discovered that the shift key doesn't display. Then I also remembered that you had a picture of a keyboard with ASCII characters in an earlier lesson. I found this one too (its in lesson 20, on Animation). But - when I put an imagewell in the ASCII Chars program to display the picture, I discovered that the character displayed on the keyboard didn't match the number of the character displayed in the msgBox!

Could you please explain a little more about keycodes? Is this difference a difference between keycodes on the Mac and the PC? And if you know where I can get a good picture of a keyboard, preferable extended, without the ASCII keycodes in the picture, just the standard characters, I would be grateful. I would like to try modifying the ASCII Char program (tedious but interesting) by putting a staticText, placard, or something over each key in the picture, and then having a mousewithin to display the keycodes for each key. This way I could display not only the basic key, but the key with modifiers. And if there is a difference in codes between Mac and PC, I could display all the codes with their application.

Since I understand that REALbasic projects can be opened on either Mac or PC, if I uploaded the uncompiled project, everybody would be able to use it.

Sincerely,

John H. Andrews

Wow, John, you're really opening a can of worms here! I'll do my best with the main question, then tackle the others.

First, note that modifier keys (Shift, Control, Command, Option/Alt, Function [PowerBook's have these]) are not available in ASCII. These are not characters -- they only modify the character typed (i.e., Shift capitalizes a letter). So the only way to test them is to ask the system. In RB, this is done with REALbasic's keyboard object.

Note there are two types of methods in the keyboard object: the async commands tell you if the modifier is press right now, while the regular commands tell if you the key was pressed when the current routine (method, event, etc.) was called. This is important, particularly in a program like SuperDraw, where you might want to know the state when the mouse button was pushed, or you might prefer to know the current state.

Now let's tackle key codes. These are completely different from ASCII or other character representations. Key codes are special numeric representations of every key on a keyboard. Because of this, while the numbers are the same for the same keyboard position, different operating systems and language keyboards (i.e., U.S. QWERTY versus French or Spanish keyboard, etc.) put different letters in different places. For instance, the key to the left of the Tab key is "Q" on the U.S. keyboard and "A" on the French keyboard, yet they both have the same key code of 0C.

Since you have no way of knowing what keyboard a user is using, it's difficult to use these key codes for practical purposes. Unfortunately, that's what the keyboard.asynckeydown command returns.

As you mentioned, there's a chart of keycodes in RBU lesson 20. That's the U.S. chart I copied from the RBD manual. As to your idea of creating your own keyboard graphic with the keycodes inside it, it could be done, but it'd a fair amount of work. You could take an existing keyboard graphic and open it in a painting program to erase the labels and then programatically add your own when the program runs. But again, you can't know what keyboard the user has connected. (In theory, with USB, the user could have multiple keyboards connected.) I'm also not sure how useful it would be do this since key codes are not used very often.

Moving on to your other questions, let's first look at the improvements to SuperDraw you were talking about. To add the Shift-key extend-selection feature, you'd want to check for keyboard.ShiftKey within the mouseDown event. You don't need to check .asyncShiftKey because you aren't concerned with the current state: you want to know the state of the key when the mouse was clicked.

Once you've determined if the Shift key was down or not, you could set yourself an object property (not local to mouseDown) to true or false to match. Then you could use that within mouseUp and the other routines to extend or not extend the selection.

As to the logic of how extending a selection should work (i.e., what happens if the user shift-clicks on the current object, etc.), I would direct you to play with other drawing programs and see how they do it, and makes SuperDraw work the same way.

Finally, you asked about the pen size, and you are correct: if you wanted full control over the pen you'd need to break the pen size into two variables to set the pen's width and height separately. That can let you draw some interesting calligraphic shapes!


About the Column
REALbasic University is a weekly instructional column on programming with REALbasic and is brought to you by REALbasic Developer, the magazine for REALbasic programmers.

Each week we answer select reader questions, and we're always open to ideas for future columns. Send your questions to . (Keep your questions simple and specific. General queries like "How do I write my own web browser?" will be neglected.) Your question won't be answered immediately, but will be answered in a future column. (If you don't want your correspondence published, just be sure to indicate that when you write. Otherwise it's fair game.)

About the Author
is an author, philosopher, graphic designer, photographer, film director, soccer fanatic, and programmer (among other things). He writes for MacOpinion, runs his own software company, Stone Table Software, which sells the revolutionary Z-Write word processor, and is Publisher and Editor of REALbasic Developer. He lives in Northern California with his cats, Mischief and Mayhem, and is rapidly running out of free time.

See the REALbasic University Archives


REALbasic University contents ©2001-2004 by Marc Zeedar and REALbasic Developer. All Rights Reserved.

Email This Article - Comment On This Article

.

Reader Specials

Server Racks Online:
Apple Xserve CompatibleServer Racks and Universal Network Racks
42U KVM Switch Solutions:
High-End Mac and Multi-Platform KVM Matrix switching solutions!
Digital Camera Online:
Great prices on Digital Cameras and accessories!
KVM Switches Online:
Great prices on Mac KVM Switches from the leading manufacturers!
LCD Monitors Online:
Great prices on LCD Monitors from the leading manufacturers!
LCD Projectors Online:
Shop online for LCD Projectors from the leading manufacturers!
USB 2.0 Online:
Great prices on USB 2.0 products from the leading manufacturers

Serious Business Software:
Accounting, Sales, Inventory, CRM, Shipping, Payroll & more!

KVM Switch solutions for MACs:
DAXTEN is a KVM switch, KVM extender and monitor splitter specialist for PC, SUN and MAC applications from name brand manufacturers - offices worldwide.

The "Think Different Store: The iPod Accessories Store - iPod cases, iPod mini, iPod photo, speakers, itrip, inMotion, Soundstage and all other iPod accessories

Earn Cash with the ThinkDifferent Store Affiliates Program

Need A Web Site?
Applelinks Web Hosting Starting at 19.95 a Month

iTunes_RGB_9mm

.

iTunes_RGB_9mm

Cool Mac Gear


iPod 1G-2G
iPod 3G
iPod 4G
iPod Mini
PowerBook-iBook
Keyboard Skins
Garageband