Re: notifications vs delegates (was: The fuzzy aspects of Cocoa)
Re: notifications vs delegates (was: The fuzzy aspects of Cocoa)
- Subject: Re: notifications vs delegates (was: The fuzzy aspects of Cocoa)
- From: email@hidden
- Date: Tue, 26 Feb 2002 19:42:36 -0800
I read this and another at cocoadevcentral and I have a question.
The stepwise article implies that notifications are slower than a
delegates... (relating to looking up in a hash table vs just using the
selector) my question here is: how much slower are they? does it
really make enough of a difference to choose one over the other in
'normal' situations?
No. Typically, you should choose the solution that better fits your
situation. The speed of notifications will only be a problem if you're
delivering hundreds of them (at least -- probably more like thousands)
per second. Assuming the method hit by the notification is quick, of
course.
The one thing I didn't notice is when to use one over the other if you
are not looking for possible veto (close window example). Suppose you
have an object (part of a framework) that wants to deliver a small chunk
of data to an interested object. Normally, this data would only be of
interest to a single object... is there a reason to choose delegates
over notifications or vice versa?
OK, I'll take a crack at this.
One big distinction is that delegates are to-one. One object creating
data of interest, one delegate for that object that is given the data.
Notifications are at least potentially to-many: for each object creating
data of interest, there can be many objects being given that data. Even
if only one other object is in fact going to listen for the data in your
current design, the "feel" of this is important to deciding which model
to use. Would it be reasonable for some other object to want to listen
as well? Is this data potentially of general interest? Or is it really
intended for, and of interest to, only one object regardless of the
implementation details you end up with?
Typically, the reason that one only object legitimately has an
interest in data generated by another object is that one object is "in
charge" of another object. NSTextView illustrates this well. Ignoring
things defined in its superclass NSText, it has only two notifications:
one when its selection changes, and another that is a little complex but
irrelevant to this discussion. It is easy to see how the selection
changing would be of general interest: one can imagine controls enabling
and disabling based upon the selection, other widgets reflecting the
selected text, inspectors showing information, toolbar buttons changing
state, etc. Each of these side effects of the selection changing could
be considered to be independant; there is not necessarily any conceptual
need for a single object that "coordinates" all this.
On the other hand, NSTextView has a bunch of delegate methods that
were not made into notifications, because they really only make sense to
a single delegate object that is "in charge" of the textview. Examples
of these messages are cells being clicked on or dragged, links being
clicked, and messages that ask for "permission" or clarification on
actions the textview plans to take. You probably would never want two
completely independant actions to occur because a link in a textview was
clicked; somebody is "in charge" of that link, and will handle whatever
consequences need to occur when it is clicked.
Another good example of this distinction is the target-action
mechanism. When a button is pressed, it is really only appropriate for
a single method on a single object to be called. This may cause a
cascade of messages to a whole bunch of objects, but there really ought
to be a single object initiating the process, because that single object
is "in charge" of that button. Target-action can be thought of, sort
of, as a delegate relationship. For the convenience of the programmer,
the action called on the "delegate" is flexible, but the essence is the
same, I think.
Another big distinction is the "looseness" of the coupling. An object
with a delegate must have an explicit (and probably retained) reference
to its delegate. It calls the appropriate method directly on its
delegate. Whether this reference is appropriate or not should strongly
drive your decision regarding whether to use delegation or notifications.
For example, it is entirely appropriate for an application to have a
direct reference to its delegate. App delegates are typically singleton
objects created for the sole purpose of "advising" and "controlling" the
application object and handling top-level application concerns.
Decoupling that relationship would be unnecessary in most cases. (Most
of NSApp's messages are of potentially general interest, however, so
they are *also* provided as notifications in most cases).
On the other hand, when your preferences panel is run and some pref is
changed, it is probably inappropriate for your preferences object to
have a direct reference to the object in your app that is governed by
that pref. That would be exposing implementation details between parts
of your app that probably can and should be modular and separate. So
posting a notification in this case often makes more sense.
The final big distinction (that I can think of right now) is that
delegates can return values, notification targets can't (or not
easily). Returning a vlue to the sender usually implies a "control"
relationship -- the delegate is affecting the object's behaviour
somehow, so it can be said to be "in charge" of that object. If you
need to return a value to the sender, that strongly implies that you
want a delegate. The one exception would be in you are conceptually
"taking a poll" or "collecting results" from however many objects happen
to respond, in which case notifications can be appropriate.
From what I gather, notifications are a bit more flexible in terms of
dynamic messages (notifications with names that are defined at run time)
but delegates are faster...
The speed difference is irrelevant to most situations; you would do
well to (mostly) forget about it, it should generally not influence you.
Notifications are more general, yes. They can go to more than one
destination, the sender doesn't need to keep references to the
receivers, etc. However, they are also more dangerous. This danger is
usually much more relevant to apps than the speed problem.
They are dangerous because it is easy for them to get out of control.
You can easily end up with an app where notification A is listened to by
a half-dozen objects, many of which send their own notifications in
response, and so on -- a single notification turns into a cascade of
mostly pointless and repetitious method calls. It is hard to believe
how insidious this can be until it happens to your own app. :-> The
delegate, being to-one in nature, tends to side-step this problem.
In summary, don't just use notifications because they're more general,
and don't just use delegates because they're cleaner, easier to
understand, or faster. Use whichever one is really appropriate given
the object design of your app, keeping in mind the principles elucidated
above.
Well, that was a lot of typing. I hope it was useful. :->
Ben Haller
Stick Software
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.