Archagon
Archagon

Reputation: 2530

Stateless static methods vs. C functions in Objective-C

In terms of good Objective-C coding practices, if I create a function that has no state, is it better to write it as a static method of some class or as a C function?

For example, I have a special filepath retrieval method that checks the Caches directory before proceeding to the main NSBundle. I currently have it as a static method under an otherwise empty Utils class. Should this be a C function instead?

The reason I've chosen to use a static method (for now) is that a) it's consistent with Objective-C syntax, and b) the class helps to categorize the method. However, I feel like I'm cheating a little, since I could easily fill up my Util class with these stateless static methods and end up with an ugly "shell class", whose sole purpose would be to hold them.

What convention do you use? Is one "better" than the other, by some objective metric? Thank you!

Upvotes: 5

Views: 817

Answers (3)

justin
justin

Reputation: 104698

If there's no class to clearly bind it to, then I use a function. I also use functions for these utility bits because they can be stripped if not used or referenced. In that regard, it's also helpful to use a function because a link error is better than a runtime error (in the even the .m was accidentally omitted from the build, or if was referenced from another externally updated method). One problem with ObjC symbols is that they do not get stripped, so they naturally carry a high amount of dependency -- all the objc methods and classes, and required category methods must exist in the final binary. That's not an issue with really small programs or libraries, but it quickly gains weight with medium/large systems and libraries.

Everything does not need to be declared in an @interface - especially with larger systems where all those declarations will really turn your interdependencies into spaghetti. Compared to methods, functions are faster, smaller, may be optimized better by the compiler or during linking, and may be stripped if not referenced.

If you need polymorphism, it just belongs in a class for organization or convenience, then a class or instance method is often a better choice.

I also minimize declaring category methods for the same reasons. When you're using functions, you can easily write a wrapper method where you need it and get the best of both worlds.

Upvotes: 1

cli_hlt
cli_hlt

Reputation: 7164

This is quite a difficult question to answer because for a lot of people the answer will depend on what their personal preferences and tastes are. I personally think that if you have a function that is a function, i.e. it has nothing to do with an object, it has no internal state etc. pp. please let it be a function and do not try to wrap everything you possibly can into an object just because you are using an OO language and you can.

In order to keep my answer short let me refer to a (imo) quite good book:

http://www.gotw.ca/publications/c++cs.htm

I know that this is for C++, but there are quite a few insights that can be shared with other languages (esp. Objective-C and Objective-C++) especially from the part called "Class Design and Inheritance". There you will find an item titeled "Prefer writing nonmember nonfriend functions".

Bottom line: "Nonmember nonfriend functions improve encapsulation by minimizing dependencies[...] They also break apart monolithic classes[...] [and] improve genericity[...]".

I think there is quite some truth in that item.

Upvotes: 1

matt
matt

Reputation: 535716

If you can think of an existing class of which this might make a good method, you can inject your method into it by making an Objective-C category. This keeps your two reasons for using a static method while not polluting the class space with an extra class.

For example:

@interface NSString (MyStringCategories) 
- (NSString*) myCoolMethod;
@end

// [StringCategories.m]
#import "StringCategories.h"

@implementation NSString (MyStringCategories)
- (NSString*) myCoolMethod {
    // do cool stuff here
    return whateverYouLike;
}
@end

Now you can send myCoolMethod to any string. Cool!

In your particular case, it sounds like a method on NSBundle might be an appropriate architecture. And don't forget, it can be a class method, so you don't need to instantiate anything in order to call your method.

Upvotes: 1

Related Questions