Saturday, October 04, 2008

Properties about a year on

Leopard has now been out for nearly a year, which means that (publicly) we've had Objective-C 2.0 for the same amount of time. At the release many developers were champing at the bit to talk about the new language capabilities[*], including properties. There were arguments on both sides of the divide, and even a little bit of discussion. But now that we've been using these things for a while, and because I'm bored awake grouchy vocal opinionated, let's have a look back at what they've given us.

There is a broken abstraction in traditional Objective-C, which is the accessor-method-as-property-declaration. Essentially an object can give you two things; work (i.e. it can do stuff) and state information (i.e. it can say stuff about itself and let you change it). In traditional object-oriented languages, because 'saying' and 'changing' are verbs which can be 'done', the two have both been expressed using the same method (heh) as the expression of work. This is not the case in much object-oriented design, for instance in UML a class always has separate "attributes" and "operations".

Properties fix up this abstraction by giving us orthogonal ways to express the two concepts. Work is done in methods; state is got/changed in properties. Now it may be that the state information is actually backed by a method (although it may bang on the ivar directly; more below), but we don't need to know that any more than we need to know in the interface that a property is synthesized or dynamic. All we do need to know is that it is there for us to use, and has certain attributes such as being read-only.

The "on more below" bit is that discussions of KVC-like mechanisms - such as KVC :-) - often involve someone pointing out that they break encapsulation, because it's possible to access an @private ivar with no accessors by retrieving it by key. That's really thinking about the design of a class in terms of the way it's executed rather than its interface contract with the developer, because the @private ought to tell the developer not to touch that particular ivar. Properties neither help nor hinder breakage from the execution side, but from the design side they do provide a stronger distinction between "properties I'm telling you about in the interface" and "things you shouldn't touch". Now we can all get back to using the class's interface to observe how to use it, and that C struct bit at the top to observe how to extend it, as nature intended. It's both a blessing and a curse that Objective-C allows things to appear in source files which don't make it into the executable code, but that doesn't stop such information being useful to the developer in the same way that code comments can be read but not executed.

One of the popular complaints about ObjC properties is the syntax for referring to them in methods (OK, or indeed in functions), where it is argued that myObject.someProperty = 4; doesn't readily tell you whether myObject is an ObjC object, a C struct or a C union. That seems to be at worst a straw man argument to me, and at best a hypothetical issue; in well-designed software it will be rare to mix code at various levels of abstraction except in limited circumstances such as adapter classes. Besides, if the code has been written such that it can be inspected or reviewed (i.e. to some agreed style and standard) and the reviewer is paying attention then it will be easy to distinguish use of the various types. At some conceptual level the C . and Objective-C . operator are doing the same thing anyway; they're both saying "this attribute of that thing".

[*]The fact that I have stopped using the word 'feature' in many contexts is an entire blog post and a few therapy sessions in itself.

4 comments:

Anonymous said...

I think the biggest complaint against Properties was that ObjC gives us two ways of using them.

[myObject setValue:100];

and

myObject.value = 100;

This is not too far different than having two ways of setting up a for loop such as:

for (i=0; i < 100; i += 2)

and

for i = 0 to 100 step 2

either one works and accomplishes the same thing but do we really need two different syntaxes to accomplish the same thing? Personally, I find the dot syntax to be confusing and it is frustrating when looking at sample code that uses both intermixed.

Add to that the fact that it might now refer to a union or a classic "C" structure (And I reject your idea that "well designed" code won't have this because it will) and it just adds further obfuscation.

Anonymous said...

I think the problem is that Objective-C (and Smalltalk from whence the Objective-C object model hails) is about message passing, not properties or methods. The simple fact is that dot notation is passing a message without the syntax to which Objective-C and Smalltalk users are accustomed.

Anonymous said...

I'm intrigued by your feature comment. Please publish said blog post!

Graham Lee said...

@bruizer: you mean, like we can't do:
BOOL exitFlag = NO;
while (exitFlag == NO) {
exitFlag == YES;
}

and

do
{
} while (NO);

because either one works and accomplishes the same thing?