Monday, May 14, 2012

Debugging Tips

In this article I am going to share a nifty way to help with debugging your code. There are times when you need to figure out which methods of your code are called when. A common solution for this is to add lines like this to your code:

Sub myMethod()
System.DebugLog CurrentMethodName + " Entered"

... your code ...

System.DebugLog CurrentMethodName + " Exited"
End Sub

This can quickly get overwhelming if the methods you want to test have lots of exit points, i.e. return statements, as you'll have to spot all of those and add a line before each of the return statements. It gets even worse if the return statement calls a function, like this:

return mySubroutine()

To get this right, you'd have to modify your code like this:

dim tmpResult as String = mySubroutine()
System.DebugLog CurrentMethodName + " Exited"
return tmpResult

But there's a much simpler solution which brings along a few other enhancements as well: 

Use an object that exists for the time the method is running, like this:

Sub myMethod()
dim myTmpObject as new MyMethodLogger(CurrentMethodName)

With this construct, the class MyMethodLogger will be constructed at the start of the method, and it'll be destructed when the method is exited, automatically. That's all thanks to RB's method of object management (it wouldn't work with the garbage disposal management as it's used by Java and Objective C).

The MyMethodLogger class just needs its constructor and destructor methods implemented, like this:

Sub Constructor(name as String)
System.DebugLog "<"+name+"> Entered"
mName = name
End Sub

Sub Destructor()
LogMsg "<"+mName+"> Exited"
End Sub

No more need to add numerous DebugLog calls before return statements.

But wait, there's more!

With that single class taking care of all the tracking, you can easily add code to have it measure the time that the method takes to execute. And it could count the depth, allowing you to indent the output, making it more readable if you have nested calls you want to trace.

For your convenience, here is a demo project with a ready-to-use MethodProfiler class:


Thomas Tempelmann, fluent in many languages, has been programming for 30 years.
Thomas has been using Real Studio for over 12 years. Thomas will be speaking at Real World 2012 and is looking forward to meeting Realbasic users in Orlando and teaching tricks and tools for Real Studio. Come by and say hello!


Mark Oxley said...

Excellent tip. I hadn't thought of using the classes in this way before.

Unknown said...

Neat. But it should be
Sub myMethod()
dim myTmpObject as new MyMethodLogger(CurrentMethodName), shouldn't it? You seem to have forgotten the "new".

Thomas Tempelmann said...

Thanks for the note about the missing "new" - fixed.