Higher-Order Messages in Cocoa
Subject:   Let HOM be your mantra
Date:   2004-09-17 07:53:31
From:   MikeAmy
Hands down? Cheers.

The inspiration is really owed to Haskell's map and fold functions. I just translated the idea into obj-c, using existing HOM implementations as a guide.

It is true that HOM reduces LOC, increases readability and reduces errors. But, I think the most important benefit is in what happens to the design.

Consider a simple while loop iterating over an array such as:


NSEnumerator *superHeroEnumerator = [superHeros objectEnumerator];
SuperHero *superHero;
while (superHero = [superHeroEnumerator nextObject])
[superHero defeatTheVillain];
[superHero saveTheGirl];

Note the while block has several statements. Several statements don't naturally go into one HOM statement. Instead we are forced to add the block onto the target. (We can always do this in Objective-C thanks to categories. Respect 'em.)

So we now have:


@implementation SuperHero
- (void) saveTheDay
[self defeatTheVillain];
[self saveTheGirl];

with our main loop being:
[[superHeros all] saveTheDay]

What happened? The block became a method on the target! Exactly where it should be. SuperHeros should know how to save the day. They don't need someone to tell them how (which is the case in [1].

Of course, we could have been a bit more insightful at the outset and used:


while (superHero = [superHeroEnumerator nextObject])
[superHero saveTheDay];

with -saveTheDay already defined as in [2]. We could then have applied the loop refactoring as before.

What this shows us is that two refactorings have occurred:
1. The block moved to the target as a method ("Extract method").
2. The loop was refactored using - all.
In this case the block refactoring was done first. The point is that doing the loop refactoring first forces the block refactoring.

HOM encourages the Law of demeter by forcing blocks onto the things that perform them. Each axis of change has been extracted in [2]. The code is much more flexible in the face of changes, which is a good thing.

NB The other alternative was to have:

[[superHeros all] defeatTheVillain];
[[superHeros all] saveTheGirl];
as our main loop.

I'll leave it as an exercise for the reader to figure out in what situations [1b] is better or worse.

Enjoy - Mike

1 to 1 of 1
  1. Let HOM be your mantra
    2005-06-23 01:14:50  DanD. [View]

    • Let HOM be your mantra
      2005-06-23 01:17:49  DanD. [View]

      • Let HOM be your mantra
        2005-06-23 16:40:08  georgerix [View]

1 to 1 of 1