7

I've started using Xcode's refactoring abilities (edit > refactor > extract) and noticed that Xcode offers to extract a method or a function.

I've read here and elsewhere about the differences between the two and understand that a method is connected to a class while a function is not. So I'm not looking for definitions, please.

Assuming that no arguments are involved, when is it appropriate to use one instead of the other? I understand that if something isn't really about the class then it could be a function but again, that's just about the definitions. I'm looking for good ol' use cases.

In my personal case, I'm trying to refactor some code out of the AppDelegate's applicationDidEnterBackground. As it is the only place to handle events upon entering the background, the only way to clean up the code is to extract subroutines into .. well, functions. But they'd be inside AppDelegate.m so wouldn't they be methods?

Hmmm..

Community
  • 1
  • 1
ari gold
  • 2,074
  • 3
  • 25
  • 51

4 Answers4

9

Personally, I only use functions if, and only if, the following two requirements are met:

  1. I use it so frequently within a given class, or throughout the project, that it warrants being generalized.
  2. It has no side-effects or context dependancies (none of that void *context mess).

In my opinion, C-style functions should only be used as a last resort or in cases where you truly need functional behavior within this kind of an application. Event handling is both application-specific, and context sensitive, so it's best if you left that alone and focused on refactoring common patterns out.

CodaFi
  • 43,043
  • 8
  • 107
  • 153
  • Are you referring to applicationDidEnterBackground when you talk about leaving event handling alone? – ari gold Jun 01 '13 at 17:03
  • @arigold I'm referring to any method at all. Event handling relies on the Responder Chain, which is a very "Objective-C" concept, and should be relegated as such. – CodaFi Jun 08 '13 at 08:14
4

You use functions when you have a, well, function ;-) You know the definitions: a method has an implicit argument self and can access instance variables using that; a function has no implicit arguments - everything it needs must be passed in.

If you are refactoring part of a larger method, that part does not access instance variables, and you are not refactoring it so that a subclass can override it, then let Xcode build you a function. When its done add static to it so it is private to the class.

In doing this you've lost nothing and made it clear that the piece of code is a function - it does not alter the state of the object.

There is of course no hard line between picking a function and a method, its a fuzzy boundary. If a piece of code, say, just accesses one or two instance variables but does not update them then you might pick a function - again making it clear that the object state is not being modified. But you don't want to pass lots of instance variables in as parameters, that is just hard to read (and inefficient).

Using functions can be good, and its certainly not bad to do so in Objective-C.

CRD
  • 52,522
  • 5
  • 70
  • 86
2

Method of a class usually need to access instance variables connected to that class. Functions in Objective-C are not connected to a class, and therefore have no access to any non-public member variables of classes.

Consider the class KNode, which contains member variable _memberVar.

@interface KNode : NSObject {
    int _memberVar;
}

@end

Any method of this class could access and change the member variable, but any old function cannot, as it is private.

@implementation KNode

- (void)modify {
    _memberVar = 10;
}

@end

The following function will not work

void modify(KNode * node) {
    _memberVar = 10;
}
Biostreem
  • 169
  • 1
  • 2
  • 8
2

Two small but meaningful advantages of functions:

  • They can be internal-only by marking them static, or __attribute__((visibility("hidden"))), which is helpful for framework developers
  • They can be inlined. For example, I use this pattern for fast lazy queue creation:

    static inline dispatch_queue_t sharedQueue() { 
        static dispatch_queue_t queue; 
        static dispatch_once_t once; 
        dispatch_once(&once, ^{ 
            queue = dispatch_queue_create("foo", 0); 
        }); 
        return queue;
    }
    
Catfish_Man
  • 41,261
  • 11
  • 67
  • 84