I realized today that one of my favorite features in REALbasic 2006r1 is the ability to get the stack crawl to an exception. It’s more useful than you’d think. I’ve always wanted to be able to write an assertion routine that worked in such a way that when an assertion failed, I could figure out exactly where that assertion was at.
For those of you who aren’t familiar with assertion-based programming, it’s where you routinely insert “assert” statements for situations you think aren’t possible, or that the code assumes aren’t possible. This way, if a bad parameter is passed in, you get a noticable failure rather than exceptions, odd results, or potentially even crashes. Thus, it’s like saying, “I assert that MyObject is not nil, and because I assert that, I will use it without even checking for nil.” The assert is actually doing the check for nil, and if it fails, it will let you know that it happened.
Well, today, I’m going to show you how to write an assert routine in REALbasic very easily:
Sub assert(condition As Boolean, failureMessage As String)
// Check to see if the condition is false
If Not condition Then
// We failed. Raise an exception
Try
Raise New RuntimeException
Catch exc As RuntimeException
// We just caught our own exception.
Dim md As New MessageDialog
Dim trimmedStack() As String
trimmedStack = exc.Stack
// Because the "assert" method will show up in the stack
// we need to remove the top-most item.
If ubound( trimmedStack ) >= 0 Then
trimmedStack.Remove( ubound( trimmedStack ) )
End If
// Prepare the error dialog
md.Message = "Failed Assertion"
md.Explanation = failureMessage + EndOfLine + EndOfLine + _
"Please send this information to the developer." + EndOfLine
Join( trimmedStack, EndOfLine )
md.ActionButton.Caption = "Quit"
md.CancelButton.Caption = "&Continue"
md.CancelButton.Visible = True
// if the user decided to quit, rather than tempt fate,
// we should quit.
If md.ShowModal = md.ActionButton Then
Quit
End If
End Try
End If
End Sub
Example usage:
Sub Something( someParam As Dictionary )
assert( someParam <> Nil, "someParam was nil" )
// use someParam
End Sub
That’s it! By raising an exception, then catching it, we can get the current stack trace, and use it to display a dialog that would help any developer figure out where an assertion is failing, which might be enough to fix the problem. This is even better than some assert routines written in other languages because it provides a complete list of the call stack, which is useful if a very common routine fails.
Have fun, and happy asserting!