« Things I miss about XcodeThe backlash of hardcore marketing »

Pet Peeves and me

I saw this article on coding pet peeves and generally agreed with most of it. I don’t get peeved if stuff happens but my style mostly matches the guy’s preferences. I depart in a few key places, though.

I need to make this disclaimer early on, especially since I neglected to do it in my first draft. A lot of my disagreements are based entirely on language and/or ideological differences. I’ll try to make explicit where this comes into play. I don’t object to Mr. Leon’s opinions, I simply hold different ones. His opinions are still valid. If I ever coalesce my list of coding pet peeves, I’m sure many others will differ as well.

Problem: Single exit points - Sure, it’s easy to complain about single exit points but they’re a boon for a lot of programmers. Mr. Leon says “we have garbage collection”, but, for many programmers, there is no garbage collection. Objective-C will eventually get GC but it doesn’t have it yet. Many times, having a single exit point allows me to make sure everything is cleaned up. As indicated, garbage collection in Objective-C may fix this. I certainly use multiple exit points when I’m scripting in Python. This is a problem based entirely on language considerations. I mention the goto statement later on which solves this problem rather conveniently when I need to do cleanup. Instead of returning, I create a label called cleanup: just before the single return where I do all my object releasing and whatnot. When I’d otherwise return early, I simply jump to cleanup.

Problem: 1000 line methods - I agree that there shouldn’t be 1000 line methods but a lot of stuff takes more than 7 to 10 lines of code. I hope the author is talking only about the terseness of Smalltalk and not about others languages. Otherwise, the only way this wouldn’t be ridiculous is for it to be hyperbole. I hear of many declarative languages having very short method counts but, simply put, standard C sometimes needs some setup and tear down in order to do a bunch of things. I think this is another language issue. We should all strive to keep method size to a minimum and make what they do simple and explicit.

Agreed: Too many comments / worthless comments - I know every says “comment, comment, comment.” I say that function names should be named appropriately and that the code kept explicit and easy to read. Complex functions should be commented. I don’t like seeing end statements nor stuff as simple as int i = 0; // initialize variable i to 0.

Absolutely disagree: Error Code - I think this goes beyond style and into some programming theory/philosophy. Error codes are an old-school way of indicating that something went wrong. They’re still around because they work. Exceptions are a nice idea, but I don’t ideologically like them. I prefer to fail silently and gracefully. I don’t want or need try/catch statements.

I think, conceptually, Apple is still on board with error codes. Sure, Objective-C/Cocoa has exception handling (and decent exception handling at that), but there’s also an NSError class. NSError is the new error code. Not only does it provide an error code, it also provides a localized string explaining the error. This is perfect for me.

My workflow is usually somewhere along the lines of:

NSDictionary *d = [self doSomethingReturningADictionary];
if (!d)
    return nil;
// Do something with d

If I fail, I return nil and I return early (if possible, see Single exit points above). I can fail gracefully and simply. Basically, I don’t have to worry if something fails because everything else is ready for it. I don’t need to catch errors and fix them later. Processors are fast enough that I can try something multiple times if the first few efforts fail. If I return early, I’m not losing that much time. On the occasion that I need a bit more information or need to fix a problem, I include an NSError. If I catch an error, then I can work around it.

NSError *err;
NSDictionary *d = [self someInternetMethodThatMayFailWithError:&err];
if (err)
{
    if ([err code] == 500)
        d = [self serviceDeniedDictionary];
    else if ([err code] == 302)
        d = [self someInternetMethodWithAlternateURL];
}

That easy, quick, and works. I prefer this to exceptions in every case. I’d rather be able to fail gracefully and silently than to have to catch every screaming baby that the app is throwing at me. Uncaught exceptions can bring down an applications. That’s just wrong in my opinion.

I think this is an ideological issue that turns into a coding style issue. On Mac OS X, uncaught exceptions can bring down applications. I really don’t think that this should be allowed. Failing silently is a virtue. It’s just counter to having to fix everything. Mr. Leon notes the Samurai Principle which is sometimes taken to mean that a method should never return nil. In Objective-C, nil is a friend. You can send messages to nil without anything breaking. Taking advantage of this is a key to simplifying methods (especially if existence checks and whatnot can be removed).

I prefer error codes for a simple reason: they can be ignored. If I haven’t beaten it hard enough, if I can fail without recourse, I’m fully willing to let code fail. Exceptions can’t be ignored. They have to be handled (especially under the Samurai Principle). NSErrors are a great effort from Apple to have error codes but also have meaningful information associated with them. I’m a fan.

Absolutely disagree: Switch Statements - I like switch statements. They’re efficient. I think they get a bad rap, like goto statements. I use both where appropriate. I refuse to give up a useful control statement.

Switch statements are often considered to be fancy if blocks but they’re so much more than that. I tend to use them if I need to do some complex things where certain stages need to take place. Consider this example where I’m making ginger ale.

switch([procedure step])
{
    case 0: // Haven't done anything
        [procedure createMiseEnPlace];
    case 1: // Add ingredients
        [procedure addSugar];
        [procedure addYeast];
        [procedure addGinger];
        [procedure addLemonJuice];
    case 2: // Finish and store
        [procedure cap];
        [procedure shake];
        [procedure uncap];
        [procedure fillWithWater];
        [procedure cap];
        [procedure setAside];
    default:
        [procedure checkAfterDelay:(60 * 60 * 24)];
}

Notice that I’m not using any break statements. This example is a good bit contrived so it’s not exactly close to real code but I do use breaks. Simply put, I can toss a procedure for making ginger ale at this switch statement and it’ll take care of all the steps no matter where it’s at in the process. Sorry for the extraneous comments but I wanted to be explicit.

Sure, I could’ve used if statements but I find this much more readable. Sometimes, these statements can be pretty complex and would be a headache if implemented using ifs. I often see switch statements as readable yet complicated ifs. That’s probably wrong on some level but it works for me.

2 comments on “Pet Peeves and me”

Ramon Leon:

December 8th, 2006 at 5:25 pm

When applied to Objective C, you have some points, but I was referring to languages with GC. As for error codes and throwing exceptions, let me give you a Smalltalk example to clarify.

This will throw an exception, as I think it should, if the item was not found.

val := someDictionary at: #someKey

Now, if I want to handle that, I don’t catch the exception, I simply call another method

val := someDictionary at: #someKey ifAbsent: [self handleErrorSomeHow]

If I want to return nil, I can

val := someDictionary at: #someKey ifAbsent: [^nil]

IMHO, error codes are simply an old technique and just have no place in programming today in languages that support exceptions.

As for switch statements, they just aren’t that useful, Smalltalk has done pretty well without them. ;) And I can always toss a few blocks into a dictionary if I really need a dispatch table.

Grayson:

December 9th, 2006 at 1:38 am

Good points and well made. I should make explicit the disclaimer at some of the disagreements that they are based on language/ideological issues. I’ll try to come up with an example of something that just seems easier to me using a switch statement. I think they’re still useful today although rapidly fading away (like the goto statement). I still stand by error codes but that’s an ideological standpoint and I’ll try to explain why I’m keen on them.

Leave a Reply