Avoiding addhandler

Lifted from another thread into its own

[quote=327678:@Kevin Windham]One place I end up using it frequently is for displaying dialogs which do something or report something to the user and the window that showed the dialog needs to know that the dialog is closed or finished with whatever it’s doing. The window will “addHandler” some method on the close event of the dialog.

Is there a better way to do this without building custom dialogs over and over again?[/quote]

there is
from my own web site
http://www.great-white-software.com/REALbasic_Code.html
look for “How to use a Dialog like a function DialogAsFunction.rbp”

Cool. Thanks.

I’m not sure if I like the way that code reads better than the AddHandler method, but it is a nice example of how to do it differently.

that code is more than 10 years old

add handler introduces points in your code that are NOT part of any documented API from that dialog/class/etc since you can just reach in and add a handler to whatever so you have a harder time knowing what the “official” API of whatever it is you’ve created is

ie/ if you instantiate a dialog and just reach in and hook the action event of that dialog to something external looking at the dialog is no longer sufficient to know that dialogs API
in fact you have a real hard time finding where these addhandlers take over the event handling of that control without reviewing a lot more code

thats why I keep saying “addhandler” allows you to create “modern” spaghetti

the way to avoid this is making all the controls on a layout private so you cannot just reach in from outside & add a handler

once you do that you might as well set up things with a proper API

if all you need / want is a way to know if a person cancelled a dialog then its pretty easy

EDIT : here http://great-white-software.com/miscellaneous/CancelDialog.zip

total time to create and upload < 5 minutes from scratch

Norm,

How would you implement the DialogAsFunction concept in a Web App? Web App dialogs are asynchronous…

You cant AFAIK

Bummer, but thank you.

I’ve been using AddHandler to create reusable classes / controls where the ‘action’ portion is slightly different. For instance:

  • Dialogs
  • Processing an uploaded image via a WebFileUploader
  • Dimming a new WebThread

I recently switched from AddressOf to WeakAddressOf based on what I read in other threads.

I really don’t want spaghetti code. Is there another way to do this without AddHandler?

well … long before AddHandler and delegates existed you could use an interface then any thing that implemented that interface had a given method that could be called
You had to have a means to set that “delegate”
That still is possible

And this is what addhandler makes easy (and hidden since its NOT part of the control/class/etc any more)
You create a suitable method on the target & just use addhandler and something outside the scope of the thing being affected now takes over control without the affected item knowing
Like AT&T reaching in and taking over answering your cell phone without you knowing
They’ve reached in and taken it and now how do you find out who has done this ?
You have to do a lot of searching for this because control is TAKEN away - not GIVEN away

And there are already interfaces in the framework for many of these things
ActionNotificationReceiver, ActionSource, etc
And you can create your own

FYI - WeakAddressOf is useful BUT has one issue
IF the target of the weak address of disappears you have no way to know and can invoke something that may now be nil
I think there is a bug report about this

From what I understand, using ActionSource has more moving parts than using AddHander which makes ActionSource not as ‘smooth’ as AddHandler.

I just checked my 6 uses of AddHander and in each case, I add the Handler on the line after dimming the object and running RemoveHander on the called method. Do you consider that spaghetti?

Thanks for your insight!

[quote=328058:@Hal Gumbert]From what I understand, using ActionSource has more moving parts than using AddHander which makes ActionSource not as ‘smooth’ as AddHandler.
[/quote]

Not saying you HAVE to use action source
Just that its an example of an interface that would let you be VERY explicit & clear about what you ARE delegating (and which controls IS doing the delegating)
AddHandler is more like something OUTSIDE the class / control stealing that responsibility - its TAKEN from under the control
I tend to prefer being very explicit and want to GIVE that responsibility away
That way I know EXACTLY where I need to look to figure out
a) what has responsibility (since I can put a break point in the code that adds whatever object as the responsible handler)
b) who gave that responsibility away (only the control could)
c) and who might have it since I can quickly find all implementors of the interface
d) that the handler “delegate” IS removed and does not cause leaks (since the control/class itself holds the reference to the delegate (and not the other way round) you can have a constructor/destructor pair that certainly removes this reference thereby avoiding leaks

We have used addhandler in the IDE (more than I care for)
And there are places where determining what is going to handle an event is a challenge because of exactly these issues
And where possible I do refactor that code to remove its use
And, as I do so, the number of outright leaks in the IDE has been coming down
So this isn’t just a rant for the sake of ranting

only slightly
why ?
because without reading the source code for the called method you would never know where the handler is removed - or if it is removed
with an interface and manually setting up the object to delegate the action handling to you can look in the method that adds the item as the delegate and in the one that removes it - both of these would exist ON that calls / control

I suppose an example of how to set all this up would help

AddHandler is seductive precisely because it is so easy to use
And that seductiveness can and often does come at a cost

Hence why I frequently counsel only using it in limited ways and NOT as a general purpose “design” because IMHO AddHandler is an abdication of “designing”

Here’s a short example

http://great-white-software.com/miscellaneous/Avoiding_Addhandler_Example.zip

Now I know I’m going to hear “But its so much more work!”
Yes it is more work
BUT NOTE That that example COULD call as many “delegates” as I wanted to set up (and could delegate out as many or as few things as you wanted)
This is something that’s harder to do with add handler
You can put a break point IN the “AddDelegate” method and see exactly what is adding itself as a delegate (which is rather hard to do with AddHandler)
And since the item that is DOING the delegating holds the references IT controls the lifetime - not the item that took over the handling
Therefore I can be sure that it does not cause leaks since the destructor will make sure all delegates are removed

And fwiw IF you wanted to you COULD use introspection at runtime & find out IF the delegates implement the methods (effectively figure out if anyone handles the event) - something you cant do with AddHandler

And this IS how it was done before AddHandler - the old IDE used this pattern extensively since most of the code predated the addition of addhandler

Thank you so much for all your thoughts. I learn more and more about the language every year.

I’m still ignorant about AddressOf and WeakAddressOf. Why would you use one or the other?

AddressOf creates a hard reference to the object and the method in the object.
This means that the object that holds that method cannot go out of scope until the handler is removed.

WeakAddressOf creates a weak reference.
This allows the object that holds the method to go out of scope & be destroyed even though removehandler has not been called.

Say you have an object that has a method that is defined on a Window and used as the handler for some event from an object outside the window (maybe some kind of notification system)

With AddressOf the end user could close the window but the window would not get destroyed because the handler is still in place - so you would need code to remove the handler and if that was the last reference then the window would be destroyed

With WeakAddressOf the end user could close the window and the window could get destroyed if that was the last reference
BUT and heres the rub
WeakAddressOf you cannot tell IF the thing that holds the method IS nil or not

For this reason I tend to avoid using WeakAddressOf as it can lead to weird nil object exceptions in a situation like I described

That sounds like WeakAddressOf is a good choice to avoid memory issues if RemoveHandler never runs.

Is this what you said?

  • If I use AddressOf, don’t RemoveHandler, the user closes the window then that memory will be held up until the app quits.
  • If I use WeakAddressOf, don’t RemoveHandler, the user closes the window then the memory will be released.

Where might you run into a nil object exception with WeakAddress? Once the Window is gone, then the AddHandler method would never be called, right?

[quote=328228:@Hal Gumbert]That sounds like WeakAddressOf is a good choice to avoid memory issues if RemoveHandler never runs.

Is this what you said?

  • If I use AddressOf, don’t RemoveHandler, the user closes the window then that memory will be held up until the app quits.
  • If I use WeakAddressOf, don’t RemoveHandler, the user closes the window then the memory will be released.

Where might you run into a nil object exception with WeakAddress? Once the Window is gone, then the AddHandler method would never be called, right?[/quote]

Say you used weakaddressof
And whatever your class does internally raises an event that you set up with addhandler & weakaddressof pointing to a method on a window that is now closed
There is a possibility this will cause some weird exception because the actual object is now nil, the event handler is nil and there is no way for you to know or do anything about it. The framework does try and help you out and this may in fact NOT cause an exception.
But suppose instead of a window its an instance of some other class that you set to nil
The framework may not be able to help you out there and now you can get a weird exception because the target object & method have disappeared.
What I’m describing is this <https://xojo.com/issue/26060>

And you get weird hard to track down bugs like this <https://xojo.com/issue/40246>

IF you HAVE to use AddHandler I’d use AddHandler with AddressOf and make sure to pair that with RemoveHandler

I see what you mean. Thank you Norman!

[quote=328215:@Norman Palardy]WeakAddressOf you cannot tell IF the thing that holds the method IS nil or not

For this reason I tend to avoid using WeakAddressOf as it can lead to weird nil object exceptions in a situation like I described[/quote]
I can vouch that terrible things can happen from this…

Fire and brimstone coming down from the skies. Rivers and seas boiling.
Forty years of darkness. Earthquakes, volcanoes…
The dead rising from the grave.
Human sacrifice, dogs and cats living together – mass hysteria.

ok maybe not THAT bad but … yeah … broken toes :stuck_out_tongue:

[quote=328293:@Norman Palardy]Human sacrifice, dogs and cats living together – mass hysteria.

ok maybe not THAT bad but … yeah … broken toes :P[/quote]
Marshmellows for all.

mmmmmmm … nummy nummy