Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In Objective-C, there are several methods like initWithContentsOfFile:encoding:error: where one passes in a reference to an NSError object for the error: parameter. In this example, the value of the NSError object passed in can change based on what goes on at runtime when the method is being called and whether the body of the method was executed in a certain way successfully. In a way I think of this NSError object as sort of like a second return value from the method, and only differs from an object anObject in the statement return anObject; in that when this statement is called, execution leaves the method.

So my question is, not only in the context of error handling in Objective-C, but in general, when should one use an "out" parameter in place of returning said value in a return statement?

share|improve this question
add comment

3 Answers

up vote 1 down vote accepted

In the case of the NSString initWithContentsOfFile:encoding:error: method that you cite, an error is handled by returning nil from the initializer. If this happens, then you can interrogate the error object (if you provided one) to get details about the error.

NSError *error = nil;
NSString *someString = [[NSString alloc] initWithContentsOfFile:somePath encoding:someEncoding error:&error];
if (!someString) {
    // oops - check out the error
} else {
    // continue using the string
}

Basically, this method design pattern needs to be in place because the return value can't be used to provide error information. The return type needs to be the initialized object (or nil). So the only option for getting more detailed error information is to provide the "out" parameter for the error.

To answer your more general question, the only time I've ever used an "out" parameter is when the method needs to return a primary value but you also need a secondary return value.

I can't think of any void methods that have "out" parameters (in the iOS SDK).

NSString gives us a non-error example with the initWithContentsOfFile:usedEncoding:error: initializer. The usedEncoding parameter is an "out" parameter. The primary return value is the string. The secondary return value is the encoding that was used to convert the file to a string.

share|improve this answer
    
Thanks for the answer. I just have a little add-on: could an array be used in some situations to avoid this situation? For example, you say that you've used an "out" parameter when the method needs to return both a primary and a secondary return values, so instead of following that pattern, could you put the primary and secondary return values in an array and return that? –  qegal Dec 5 '12 at 2:28
    
@rmaddy. Why do you think is the reason why the language designers decided to use the error parameter instead of rising an exception ? –  user61852 Dec 5 '12 at 2:57
    
@qegal You could use an array for the return value but I think it is a bad idea because you lose clarity. With a clear return type and and a clear out parameter, it is easy to understand and document. If you change to using an array, that is all lost. It becomes too easy to lose track of what is in the array. The compiler can't verify you are using the correct objects. –  rmaddy Dec 5 '12 at 3:09
    
@user1598390 Exceptions are meant for exceptional events. Exception processing in Objective-C is expensive. An exception is meant for something you really didn't expect and many times can't really handle. I know Java does everything with exceptions. This was a decision made by Gosling and company. The Apple folks that wrote the Cocoa framework decided to handle errors the way they do. Some things do result in exceptions such as passing in invalid parameter values. Those are truly exceptional cases, not just errors. –  rmaddy Dec 5 '12 at 3:13
1  
Just throwing out there because you say the only time I've ever used an "out" parameter is when the method needs to return a primary value but you also need a secondary return value which is common and I don't know if there is support for it in Objective-C but another approach is to use tuples or fixed-expectation arrays which kind of stink or objects with nullable properties. In these ways you return multiple values through the return rather than through the parameters list. For instance this is a necessity in web services where out parameters don't make sense as you aren't sharing a heap. –  Jimmy Hoffa Dec 5 '12 at 7:09
show 3 more comments

This, to me, just looks like a poor initial API design choice that couldn't have been fixed without breaking a lot of existing binaries.

It's pretty much standard that if a function does something that may fail, then the success/failure is flagged through the return value, and if anything else needs to be returned it's done through a parameter that's passed by reference.

The way your example is defined does nothing (that I can see) to make the developer's life easier, unless it's the type of developer who assumes nothing can go wrong. I'm not sure how static analysis tools would cope with this convention either.

share|improve this answer
3  
That's not "standard" among all languages. It's pretty controversial in C# to flag failure through return, though in Haskell it's utterly idiomatic, different languages have different acceptable practices. Personally I hate out parameters altogether as do a great many people, so perhaps you should say that's a common practice, though it's controversial at best. (I cannot stand the TryParse idiom) –  Jimmy Hoffa Dec 5 '12 at 1:59
    
@Jimmy Hoffa: Funnily enough C# is one language I've never used. I was referring to my experience of different APIs and Frameworks on different OSes. I'll add that I didn't realise either that NSError is an object which invalidates my argument somewhat - but then I can't think off the top of my head of other languages that have ErrorCode Objects. I believe it still would hold if NSError was a normal int type return code. –  James Dec 5 '12 at 3:01
    
The method does have a value to flag failure—nil—but the NSError object provides more specific information on why an error occurred. –  mipadi Dec 5 '12 at 5:45
add comment

IMO (emphasis on the O), you should avoid out parameters whenever you can. I don't know anything about Objective-C, but if this were Java you'd throw an exception instead of using an out parameter.

Exceptions were created to keep your exceptional logic out of the way of normal flow control. In theory, this makes the code easier to read because it doesn't have to look like this:

Object something = doSomething();
if (something == isValid())
    Object somethingElse = doSomethingElse();
    if (somethingElse == isValid())
        ...
    else
        //handle what happens when "something else" goes wrong
else
    //handle what happens when "something" goes wrong

Instead, it can look like this:

try {
   Object something = doSomething();
   Object somethingElse = doSomethingElse();
   ...
} catch (SomethingException e) {
    //handle what happens when "something" goes wrong
} catch (SomethingElseException e) {
    //handle what happens when "something else" goes wrong
}

What I like about the latter is the typical flow can be read sequentially.

You do something, then you do something else, then you ...

With the first example, your error handling is all mixed up together with that logic instead of out of the way in the off chance that it happens.

If Objective-C has exceptions, I think the API would have been better written if it used them in this case. If it doesn't have them, I assume it at least has Objects. It could have returned some type of response object that you can query to find out if the response had errors.

share|improve this answer
    
Objective-C does have exceptions, but they are indeed exceptional, not just an error code. –  K.Steff Jan 4 '13 at 1:23
    
Why isn't this error considered exceptional? –  tieTYT Jan 4 '13 at 1:26
    
Because in many cases errors are not exceptional: in this case you are not certain the file is in the encoding you provide (e.g. ASCII and characters above 127). Needless to mention things like network connections, where on a mobile device with 3G, actually completing all requests without any errors would be the exception. –  K.Steff Jan 4 '13 at 1:38
    
I think it's subjective whether those cases are exceptional or not. When it comes to the first method, it's really context dependent. Whether or not these examples fall under the definition of "exceptional" is minor compared to how much cleaner the code could be if it avoided an out parameter. –  tieTYT Jan 4 '13 at 1:54
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.