Reversing the polarity of the message flow

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.]

About Graham

I make it faster and easier for you to create high-quality code.
This entry was posted in OOP. Bookmark the permalink.