Building for Better Crash Reports

I think developers spend too much time optimizing for the wrong things. Most of the time we optimize the elegance of our code. Sometimes we optimize the execution of our code.

I spend a lot of time debugging code, and when I’m debugging, I’m usually not looking at source code or code being executed. I’m looking at crash reports.

So now I optimize for crash reports.

Here is one example. Imagine we have a method like this:

- (void) methodThatMightCrash { ... }

and because methodThatMightCrash is so useful we call it all over the place. But lets also say methodThatMightCrash needs to be invoked on the main thread. So all over the place we have code like this:

[self performSelectorOnMainThread:@selector (methodThatMightCrash:) withObject:nil waitUntilDone:NO];

Now, lets go out on a limb and say methodThatMightCrash crashes. The stack trace we get in the crash report is going to be useless. We wont have any idea what the state of the application was when methodThatMightCrash was invoked or why it was invoked.

To get better crash reports I do stuff like this:

- (void) someMethod
{
    if (someState) {
        [self queueMethodThatMightCrashBecauseSomeMethodIsInSomeState];
        return;
    }

    [self queueMethodThatMightCrashFromSomeMethod];
}

- (void) queueMethodThatMightCrashBecauseSomeMethodIsInSomeState
{
    [self performSelectorOnMainThread:@selector (methodThatMightCrash:) withObject:nil waitUntilDone:NO];
}

- (void) queueMethodThatMightCrashFromSomeMethod
{
    [self performSelectorOnMainThread:@selector (methodThatMightCrash:) withObject:nil waitUntilDone:NO];
}

Those method names are a little scary, but trust me, you will be happy to see one in a crash report.