Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

nashyo

macrumors 6502
Original poster
Oct 1, 2010
299
0
Bristol
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

Code:
-(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?
 
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...
 
Unless you're planning on catching an exception, don't throw it, since you're effectively crashing your app.

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.

Right?
 
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:

http://en.wikipedia.org/wiki/Introspection_(computer_science)
 
Last edited by a moderator:
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.

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:
https://developer.apple.com/library...ns.html#//apple_ref/doc/uid/20000056-BAJDDGGD


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.


Test driven development doesn't seem prevalent at the front end. If this is the case, then why?
Please explain what you mean by "at the front end".
 
Please explain what you mean by "at the front end".

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 think maybe you don't know what introspection means:

I know what introspection means. I started the thread.
 
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.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.