Newsgroups: comp.lang.smalltalk
Path: cantaloupe.srv.cs.cmu.edu!europa.chnt.gtegsc.com!howland.reston.ans.net!math.ohio-state.edu!news.cyberstore.ca!vanbc.wimsey.com!fonorola!news!dbuck
From: dbuck@infoweb.magi.com (David Buck)
Subject: Re: Eliminating procedural code
Sender: news@magi.com
Message-ID: <DACI84.7zJ@magi.com>
Date: Sun, 18 Jun 1995 01:45:40 GMT
References: <DAA0E1.8un@stortek.com>
Nntp-Posting-Host: infoweb.magi.com
Organization: Magi Data Consulting
Lines: 61

In article <DAA0E1.8un@stortek.com>, Alec Sharp <alec@k1.stortek.com> wrote:
>Question: What alternative ways have you seen or used to eliminate
>procedural code?
>
>  <sample code clipped>
>
>In our product, to get rid of the procedural nature, we tell the object
>to tell us to process it. For example, in MyClass:
>
>myProcessObject: anObject
>   anObject processYourselfVia: self
>
>Then in the object, we see
>
>SuccessObject>>processYourselfVia: anObject
>    anObject processSuccess: self
>...

This technique is known as a double-dispatch.  It's a common technique in 
Smalltalk programming.

>A problem with this scheme is that when additional objects are added
>to the product and can appear in one of these shared queues, we have
>to make sure that we add a processXXXX: method to MyClass. (Although
>any problem should appear pretty soon if any testing is done.)

My question is:  Why can't the objects on the queue do the processing 
themselves?  Does MyClass really have to have the responsibility of 
handling successes, failures, and heartbeats?  Can the success, failure, 
and heartbeat objects take this responsibility themselves.  If MyClass 
really needs to accept this responsibility, then you need those process... 
methods regardless of whether or not you have objects for success, 
failure, heartbeat, etc.  If you add a new method to MyClass just because 
you have a new kind of object you can put in the queue, I would argue 
that MyClass shouldn't be responsible for doing this work.

>An alternative way is to have MyClass define:
>
>myProcessObject: anObject
>    selector := anObject processingMethod.
>    (self respondsTo: selector)
>	ifTrue: [self perform: selector with: anObject]
>	ifFalse: [self doSomeErrorStuff]

This solution doesn't solve the problem.  It's more inefficient because 
perform: isn't the fastest method in the world.  It still requires 
MyClass to implement all the functionality on behalf of the objects you 
put into the queue.  All that's changed is the way the methods are invoked.

I think your best bet here is to remove the process... methods from 
MyClass.  The processYourselfVia: methods (I'd prefer a name like 
processUsing:) should implement the fuctionality themselves rather than 
double-dispatching back to MyClass.

Of course, I don't know all the details of your system.  Your mileage may 
vary.

David Buck
dbuck@magi.com
The Object People

