Ad

Our DNA is written in Swift
Jump

Coding Style

Dany asked:

I’m looking at your (nice) project NSAttributedString-Additions-for-HTML and I have some questions about your convention of writing code.
I really hope that you can reply to me, and maybe can be an idea for a future blog post (on naming conventions, and conventions in general for objective-c).

I adopted several styles I read about in the coding style guides by Google and Marcus Zarra, though I have to admit I only skimmed through these and picket a couple of things that made sense.

Though it is good practice to reflect on your style every once in a while to see if it still serves the purpose of making your code easier to maintain and read.

Because there where several questions, let me alternate them and my answers:

You sometime put @property on .m and not in .h, you do for private variables? if so why don’t use @private?

A property is basically a shortcut to get a getter and setter method created for you. Getter-only if you specify readonly. Now for instance variables that are pointers to objects you probably want to retain these. So you specify the retain tag in the property definition. Such a retaining property releases the previous value and retains the new one, the standard implementation would look something like:

@property (nonatomic, retain) NSObject *someObject;
@synthesize someObject;
 
// becomes:
 
- (void)setSomeObject:(NSObject *)aObject
{
   if (someObject != aObject) // avoid release if no change
   {
      [someObject release]; // release previous value
      someObject = [aObject retain]; // retain new value
   }
}
 
- (NSObject *)someObject
{
   return someObject;
}

So having this ivar as a property saves me quite a bit of work with the release and retain. While that is more convenient for me, I don’t necessary want to expose all these values to outside callers. Because of that I moved the property definition into a private header extension which you can recognized by the empty category name in round brackets. This way the properties are being generated, but are not visible or callable from outside.

Now with ARC that is not so much important any more because you don’t specify release or retain. So you can safely assume that this is sort of “Pre-ARC Style” and will go the way of the dodo bird.

Sometime aren’t used @property at all, in which case exactly? I know that this just mean to use the iVar without getter\setter, but in which case you prefer to do it?

A property for a scalar value (like NSInteger, CGFloat) does the same as using the ivar directly. So I never used properties for setting/getting those because it actually adds the overhead of a function call and return as opposed to accessing the value directly from within the class.

Same question for methods prototype, you sometime put it in .m, you do this for private method? and so you keep only public method on .h?

Exactly. If I have a method that I am encapsulating some functionality in that is to be called from several places inside the class code then I still want to hide that from the outside world.

I see another thing that i don’t understand, you sometime write in your .h. why that? 2 property for the same iVar one with “readonly” in .h and the other without it in .m?

@interface YourClass : NSObject
{
   NSArray *anArray;
}
@property (nonatomic, retain, readonly) NSArray *anArray;
 
and in .m
@interface YourClass ()
   @property (nonatomic, retain) NSArray *anArray;
@end

This is the private class header extension (via anonymous category) I alluded to above. The synthesize generates a method to set the array but I only want that to be accessible from inside the .m implementation. Otherwise somebody would be able to mess with where the array ivar points to with possible unexpected consequences. You want to only allow outside callers access to the minimum amount of ivars and methods possible.

Another question, you use the prefix _ only for some iVar. Why that? Is not preferable to have always or never?

UIColor *_textColor;
UIColor *backgroundColor;
and then in .m
@synthesize textColor = _textColor;
@synthesize backgroundColor;

You see me doing that if I am overwriting a property’s setter with my own code, probably because I want something else to be triggered when the property is used. For example with the textColor you might also want to call setNeedsDisplay on the view so that the text gets redrawn with the new color.

I don’t like having to invent the name of the parameter for the setter with something preceding it with an a or an, but rather want the passed parameter to have the same name as the property.

- (void)setTextColor:(UIColor *)aTextColor
- (void)setTextColor:(UIColor *)textColor // better

Now if the name of the parameter is to be textColor then I have a problem inside this code block because the ivar has the same name. So how should the compiler know whether you mean textColor, the parameter or textColor, the ivar? Using the underscore prefix is the traditional method to have the ivar have a different name, but without messing up how it looks, because the small underscore does not hurt when reading the code.

Last question (I hope): You sometime use @synthesize and sometime implement the setter\getter manually, you do that only to add some custom behavior, right? Like call a method if the variable change.

That’s exactly the reason. If you have both a synthesize and a manual implementation of the setter method then the compiler will use manual implementation. I explained above how you sometimes need to trigger something when the setter is invoked.

Conclusion

Dany’s questions made me think about the use of properties in ARC-projects. Because you don’t need retain/release any more you probably also need to implement much fewer properties, even for internal use.

With the latest version of Apple’s LLVM compiler you also get another way of hiding unnecessary info from developers. You no longer need to define all ivars that are backing properties. Also you can now put the ivar definitions into the @implementation. But this possibility blew mind mind when I first heard about it. That’s crazy!

One reason why you DON’T want to hide everything is that you might restrict access to variables and member methods which are internal to the class too much. Like you would make it impossible for sub-classes to know about and access these. Remember that the .h file is also all that the child class knows about its super class.

If I have to come up with a rule for that:

  • Hide external setters it if access by other developers breaks your class.
  • Don’t hide IVARs if you foresee that your class might be subclassed and these IVARs need to be accessible.

Categories: Q&A

4 Comments »

  1. The last rule can read like this: hide private IVARs but don’t hide the protected ones.

    If I record well “protected” is the default. If you put @private the subclasses won’t have access.

  2. I might be missing something, but the problem I’ve had with not explicitly declaring an ivar for properties is (the lack of) visibility in the debugger. But I do like the more concise .h file that results.

    Slightly off-topic, but related; do you init your properties with autorelease or explicitly release them in dealloc?

    I used to do the latter but have recently heard good arguments for the former. I’m trying to adjust, but it still feels wrong (lazy) to be autoreleasing objects I own.

    Although IMO only factories should be allocating new objects anyway (which, by definition, are already autoreleased) but of course that’s another kettle of fish 🙂

  3. With regard to the last question on manually implementing setters and getters to trigger, say, another method when a property changes, what are your thoughts on using KVO for this purpose instead? Would you say that’s more or less maintainable?

    To me, it always feels like it leaves a cleaner code base, but it’s definitely less clear as to what’s going on at first glance.

  4. I very rarely use KVO because of several reasons including code readbility and that you need to properly remove listeners.