On receiving a message with a parameter, sometimes an object just reverses the sense of what just happened and sends another message to the parameter object with itself as the parameter of this message. That’s a pretty hard sentence to read, but I couldn’t work out how to rewrite it, so here’s an example. A Smalltalk class might have a method like this:
Object>>#printOn:
printOn:aStream
"Append to the argument, aStream, a sequence of characters
that describes the receiver."
|description|
description := self description.
aStream nextPutAll:description.
I would do this as a matter of design: I can make it clear that I’m messaging one object and using another simply in a supporting role. It takes this:
foo doTheThing.
aStream nextPutAll:foo description.
and turns it into this:
foo doTheThing;
printOn:aStream.
In Objective-C, this pattern has an additional use due to the nil
sink for messages. Imagine formatting a string and appending the result to another string, but if the initial string is nil
then you don’t want to add anything. It might look like this:
if (emailText) {
NSString *quotedString = [NSString stringWithFormat:@"> %@", emailText];
[output appendString:quotedString];
}
because I don’t want the phrase > (null)
to appear in the output. But, with a bit of category magic, we can avoid the condition and make it clear that the email text is the important object.
[[emailText quote] appendTo:output];
I haven’t just hidden the conditional; it never appears. If emailText
is nil
then all the other messages will just get dropped, so neither quote
nor appendTo:
need to test for nil
.
Sometimes, the messages are just flowing the wrong way, and clarity can be gained by reversing the polarity.
[Update: oops! I had read Kent Beck’s “Smalltalk Best Practice Patterns”, and apparently absorbed his Reversing Method pattern. This post is basically a discussion of that pattern, and credit should go to Kent for originally creating it. My addition is the Objective-C specific nil
sink extension. Sorry, Kent.]