When to use introspection

Discussion in 'iOS Programming' started by nashyo, Feb 16, 2013.

  1. nashyo macrumors 6502


    Oct 1, 2010
    I've been programming for iOS for about 18 months now and I have no experience doing anything else related.

    I still have questions regarding the simple fundamentals that have bugged me since the beginning.

    Q: Introspection and exceptions
    If I examine an NSDictionary for a key value pair, should i perform introspection on the object I find to ensure it is what I expect it to be? How paranoid is too paranoid?

    If I don't get what I expect, how do I handle it?

    Simple example

    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
        NSString *segueID = segue.identifier;
        id destinationViewController = segue.destinationViewController;
        if ([segueID isEqualToString:LOGIN_SEGUE_ID] && [destinationViewController isKindOfClass:[LoginViewController class]])
            LoginViewController *loginVC = destinationViewController;
            loginVC.delegate = self;
            if ([sender isKindOfClass:[NSMutableDictionary class]])
                LoginMode mode = [[sender objectForKey:LOGIN_MODE_KEY] intValue];            
                loginVC.loginMode = mode;
    This question specifically has bugged me since the beginning, and my related unit testing questions have also been brushed off by passers by in the iOS community.

    Test driven development doesn't seem prevalent at the front end. If this is the case, then why?
  2. ArtOfWarfare macrumors G3


    Nov 26, 2007
    If it should be one thing and it isn't, then depending on the severity of the issue you have options such as:

    Throw an exception.
    Pop up an alert

    ... I can't think of much else you could do, if you wanted to do anything. I suppose you could trash the array and start from scratch putting what you want into it...
  3. dejo Moderator


    Staff Member

    Sep 2, 2004
    The Centennial State
    Unless you're planning on catching an exception, don't throw it, since you're effectively crashing your app.
  4. nashyo thread starter macrumors 6502


    Oct 1, 2010
    That's exactly it...planning to catch exceptions?

    If something isn't what you expect it to be, at any point in your code, you should handle it in some way, and not skip any introspection, anywhere. Ever.

  5. PhoneyDeveloper, Feb 16, 2013
    Last edited by a moderator: Feb 16, 2013

    PhoneyDeveloper macrumors 68040


    Sep 2, 2008
    As in many things, it all depends.

    If a method has a contract and the contract is violated then you can assert, which throws an exception and crashes your app. This is the idiom followed by Apple. They call it "programmer error" and it results in the widely seen SIGABRT error. It's a reasonable policy that should result in higher quality code.

    Learn to use the NSAssert() macro. It's another way to test your code. It's similar to unit testing in some ways.

    Introspection is completely orthogonal to this however. In general I prefer to have designs that avoid introspection except maybe for respondsToSelector with delegates. I would prefer to have a requirement for the types of objects that are found in a given container. So if you have a dictionary that has a key/value pair where the key is @"name" the value must be a string. It can't be a number or some other random object. I probably don't have code that verifies this though. Most likely if the name isn't a string and the code tries to use it as a string there will be an assertion failure. If you want to use NSAssert() to verify the kind of objects found in your containers matches your contract that might make sense. In most cases I'd find that to be over the top though.

    I think maybe you don't know what introspection means:

  6. chown33 macrumors 604

    Aug 9, 2009
    Objective-C already does that, to some extent. If you try to send a message to an object that doesn't have a method, then the objc_msgSend fails.

    You can add a function to catch uncaught exceptions:

    If you're looking for more type-safety than that supplied by other means, you can wrap an NSDictionary or NSMutableDictionary in a class of your own making, and enforce the type-safety there. You shouldn't do this by subclassing, because the collection classes are class clusters.

    A class wrapper is also a better design than sprinkling a bunch of type-checks through the code. The reason is similar to why magic numbers are bad: Don't Repeat Yourself. A class is a centralized locus of behavior, so if (when) it needs to be changed, it can be done in one place and all others get the change automatically.

    By the way, I don't really see the purpose of your posted code. If the 'sender' object isn't an NSMutableDictionary, the method doesn't complete its task. It doesn't roll back what it already did, either, possibly leaving the program in an inconsistent state (cascade failure likely). This can be a bad idea, because it hides fundamental errors.

    When testing, I would much rather know about such fundamental errors, rather than be writing code that masks them. Masking errors kinda defeats the purpose of test-driven programming,

    If some piece of code can't work with objects other than a specific type, then it should stop working in an obvious way, such as by failing an assertion. It should NOT quietly accept an unusable parameter and quietly do only part of what its entire task should be.

    Please explain what you mean by "at the front end".
  7. nashyo thread starter macrumors 6502


    Oct 1, 2010
    Back end development being server side dev and front end development being user side. At least that's my interpretation.

    By the way you post makes a lot of sense. I shouldn't be allowing my code to quietly fail.

    I will look into NSAssert.


    I know what introspection means. I started the thread.
  8. Ides macrumors member

    Mar 27, 2012
    In my experience with ios development, Ive found that really the only use ive had for introspection is with delegates/protocols. Its important for "optional" delegate methods.

Share This Page