delegation (was: prototypical analysis and design)
Jecel Assumpcao Jr
jecel at merlintec.com
Wed Nov 22 20:02:40 UTC 2000
On Tue, 21 Nov 2000, Bharat Bedia wrote:
> Secondly, all I have is my hands-on experience - I'm pretty low on
> the theoretical side.
Me too. I was attracted to the practical side of Self's "exploratory
programming" style. Since you were asking about "analysis", I thought
you meant things like Booch and UML and other things that I am not
familiar with, which is why I made no comment.
> I think there are several issues but for now
> I'm only going to mention two: 1. patterns, and 2. the prototype
It would be very interesting to go through all the patterns in the
"Design Patterns" book (which I have just read) and look at them from
the viewpoint of a prototype based language. I'll try to do so later,
but for now I would just like to clear up some confusion about
"delegation" and Self:
If you define "inheritance" as a relation between two classes and
"delegation" as a relation between two objects, then it seems natural
to think that Self only has delegation but not inheritance. In fact,
more than one paper I have read claim just that! But this ignores the
fact that you can create objects in Self that behave like classes in
other languages. I feel it is less confusing to say an object
"inherits" from such objects than to claim it "delegates" to them. Here
are some ways to organize objects in Self:
1) constant parent slots - these nearly always point to some
class-like object (traits something). You normally make no explicit
reference to this slot in your code (just like the "class" field is
normally hidden in most class-based languages) but only deal with it
through the programming environment.
2) data parent slots - while Self is famous for these, they are very
rarely used. See the various tree collection objects for a good (only?)
example. You normally have to reference these slots explicitly since
you sometimes want to change their value (or they would be constant
slots instead, right?).
3) _Perform:DelegatingTo: primitive - this allows you to send a
message to the receiver but do the lookup in another object. I have
never tried this and don't know if this other object must be a parent
of the first (and so equivalent to what you can do with the directed
resend syntax) or if it can be any object (generic delegation, which is
not possible with the normal Self syntax).
4) data slots - you can explicitly resend a message you receive to
any object you have a reference to.
1 and 4 are available in Smalltalk or C++, and so make no difference in
terms of design patterns.
2 (and specially 3, if it allows generic delegation) certainly make
many design patterns, like the Strategy pattern for example, cleaner.
Some patterns, like Facade and Adapter, require explicit delegation
(4 - since they change the message selectors) which other languages
handle as just as well as Self.
But the issue that you mentioned was prototype based programming. That
obviously has an effect in the various object creation patterns such as
Prototype (obviously redundant) and Singleton. I feel that prototype
based programming goes naturally with persistent object systems (which
means Snapshots in Self 4.1.2) - then you can use all of the resources
in the system (a paint program, for example) to create your prototype
and easily make a few clones when your application needs them.
Otherwise you will have to explicitly code the object's construction
(an init method full of "addMorph:") as in the Builder pattern.
More information about the Self-interest