[Discussion] Warning vs. Halt (or: "Why is a warning a notification?")

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

[Discussion] Warning vs. Halt (or: "Why is a warning a notification?")

marcel.taeumel
Hi, there.

At the moment, we have this hierarchy in Squeak's exception mechanism:

Exception < Error
Exception < Notification < Warning
Exception < Halt
Exception < UnhandledError < UnhandledWarning

I think that something is conceptually wrong here. Notifications are supposed to be resumable and do nothing by default. Warnings, on the other hand, are resumable but interrupt the process by default. Like Halt does.

Not now, but in the future, I would like to change it to something like this:

Exception < Error
Exception < Notification
Exception < ResumableInterrupt < Warning
Exception < ResumableInterrupt < Halt
Exception < UnhandledError < UnhandledWarning

Thoughts? Well, there are other notifications that interrupt the current process in a way: EnvironmentRequest, MCMergeResolutionRequest, ... Maybe my definition of "Notification" is wrong?

Best,
Marcel

P.S.: Why is CurrentReadOnlySourceFiles an Exception but CurrentEnvironment is a Notification? Sigh....


Reply | Threaded
Open this post in threaded view
|

Re: [Discussion] Warning vs. Halt (or: "Why is a warning a notification?")

Chris Muller-3
Hi Marcel,

At the moment, we have this hierarchy in Squeak's exception mechanism:

Exception < Error
Exception < Notification < Warning
Exception < Halt
Exception < UnhandledError < UnhandledWarning

I think that something is conceptually wrong here. Notifications are supposed to be resumable and do nothing by default. Warnings, on the other hand, are resumable but interrupt the process by default. Like Halt does.

I agree with your above statements except for something being conceptually wrong.  It seems perfect to me.
 

Not now, but in the future, I would like to change it to something like this:

Exception < Error
Exception < Notification
Exception < ResumableInterrupt < Warning
Exception < ResumableInterrupt < Halt
Exception < UnhandledError < UnhandledWarning

Thoughts?

Hmm.  It took me a minute, but I think I see what you're _wanting_ to do.  What I don't care for, however, is mixing this notion of "Resumable" with the fact that every Exception already understands #isResumable, and so would introduce a potential ambiguity or conflict between them.  Perhaps I would like it better if it were just called "Interrupt", and leave the #isResumable nomenclature to be inherited from Exception>>#isResumable, however...
 
Well, there are other notifications that interrupt the current process in a way: EnvironmentRequest, MCMergeResolutionRequest, ... Maybe my definition of "Notification" is wrong?

... the "Interrupt" nature of the requests above is really a property _handling_, not requesting.  For example, tit's only the #defaultAction of EnvironmentRequest that interrupts, but in a headless environment, bootstrap code would wrap it to avoid that:

   [ ... ] 
     on: EnvironmentRequest
     do: 
           [ : req | 
           "custom handling, NOT an interrupt" 
           req resume ]

Similarly, an example of the need for resumable Warning is exemplified by SmalltalkImage>>#run:.  This is for headless servers, where one doesn't want an arbitrary Warning to stop the server, so the proper course of action is to log it and resume, always.

For Magma apps, I have a MagmaSessionRequest which is a Notification that is conveniently ignored unless one sets a Session.  That way, one single application code base can be run equally either, in memory, or connected to a database, without any code changes or extra configuration.

"Requests" and Warnings absolutely need the flexibility of being Notifications, not only Interrupts.  IMO, the choice to interrupt, or not, is made by the handling code.

Best,
  Chris


 

Best,
Marcel

P.S.: Why is CurrentReadOnlySourceFiles an Exception but CurrentEnvironment is a Notification? Sigh....



Reply | Threaded
Open this post in threaded view
|

Re: [Discussion] Warning vs. Halt (or: "Why is a warning a notification?")

marcel.taeumel
Are there other exception mechanisms out there that have notifications at all?

I think that it bothers me that I cannot simply catch all potential interrupts without messing up dynamic scope such as in ReadOnlySourceFiles. And interrupts are a combination of #isResumable and #defaultAction. Hmmm..... Notifcations that claim to be resumable but require user input in #defaultAction feel kind of awkwardly designed... In that sense, I can also resume any error with "nil" (or "false") if I want to.... Hmmm...

Best,
Marcel

Am 01.11.2019 02:19:43 schrieb Chris Muller <[hidden email]>:

Hi Marcel,

At the moment, we have this hierarchy in Squeak's exception mechanism:

Exception < Error
Exception < Notification < Warning
Exception < Halt
Exception < UnhandledError < UnhandledWarning

I think that something is conceptually wrong here. Notifications are supposed to be resumable and do nothing by default. Warnings, on the other hand, are resumable but interrupt the process by default. Like Halt does.

I agree with your above statements except for something being conceptually wrong.  It seems perfect to me.
 

Not now, but in the future, I would like to change it to something like this:

Exception < Error
Exception < Notification
Exception < ResumableInterrupt < Warning
Exception < ResumableInterrupt < Halt
Exception < UnhandledError < UnhandledWarning

Thoughts?

Hmm.  It took me a minute, but I think I see what you're _wanting_ to do.  What I don't care for, however, is mixing this notion of "Resumable" with the fact that every Exception already understands #isResumable, and so would introduce a potential ambiguity or conflict between them.  Perhaps I would like it better if it were just called "Interrupt", and leave the #isResumable nomenclature to be inherited from Exception>>#isResumable, however...
 
Well, there are other notifications that interrupt the current process in a way: EnvironmentRequest, MCMergeResolutionRequest, ... Maybe my definition of "Notification" is wrong?

... the "Interrupt" nature of the requests above is really a property _handling_, not requesting.  For example, tit's only the #defaultAction of EnvironmentRequest that interrupts, but in a headless environment, bootstrap code would wrap it to avoid that:

   [ ... ] 
     on: EnvironmentRequest
     do: 
           [ : req | 
           "custom handling, NOT an interrupt" 
           req resume ]

Similarly, an example of the need for resumable Warning is exemplified by SmalltalkImage>>#run:.  This is for headless servers, where one doesn't want an arbitrary Warning to stop the server, so the proper course of action is to log it and resume, always.

For Magma apps, I have a MagmaSessionRequest which is a Notification that is conveniently ignored unless one sets a Session.  That way, one single application code base can be run equally either, in memory, or connected to a database, without any code changes or extra configuration.

"Requests" and Warnings absolutely need the flexibility of being Notifications, not only Interrupts.  IMO, the choice to interrupt, or not, is made by the handling code.

Best,
  Chris


 

Best,
Marcel

P.S.: Why is CurrentReadOnlySourceFiles an Exception but CurrentEnvironment is a Notification? Sigh....



Reply | Threaded
Open this post in threaded view
|

Re: [Discussion] Warning vs. Halt (or: "Why is a warning a notification?")

Jakob Reschke
Marcel Taeumel <[hidden email]> schrieb am Sa., 2. Nov. 2019, 13:54:
Are there other exception mechanisms out there that have notifications at all?

In Common Lisp exceptions are called conditions and error is a subtype of condition. However whether a debugger appears in case of an unhandled condition is not determined by the type of the condition, but by whether the condition was signalled with the function #'signal or with the function #'error. The latter establishes a default handler that opens the debugger.


Reply | Threaded
Open this post in threaded view
|

Re: [Discussion] Warning vs. Halt (or: "Why is a warning a notification?")

Jakob Reschke
In reply to this post by marcel.taeumel
Marcel Taeumel <[hidden email]> schrieb am Sa., 2. Nov. 2019, 13:54:
Hmmm..... Notifcations that claim to be resumable but require user input in #defaultAction feel kind of awkwardly designed...

Yes they are. After all they don't really have a default value that should be automatically determined. Or in other words they must be handled and if they are not they force you to handle them manually. In that regard they behave more like Errors, which are manually handled in the debugger. They are not errors from a functional perspective though.

In that sense, I can also resume any error with "nil" (or "false") if I want to....

...which is what you get when you press "proceed", right? But you are not allowed to send #resume or #resume: to them.

#resume with default value does not make much sense for those request exceptions either.

A more sensible pattern might be:

    value := RequestNotification signal.
    value ifNil: [self showUiRequest].

But you cannot enforce it anyway.

Also these requests are mostly UI situations which want to be unit-testable and therefore use these exceptions, aren't they? So they might not be amenable or relevant for catch-all exception handling for server purposes anyway.


Reply | Threaded
Open this post in threaded view
|

Re: [Discussion] Warning vs. Halt (or: "Why is a warning a notification?")

Christoph Thiede

Hi all,


as you're talking about UI notifications, I would like to add my 2 cents:


I have always found the UIManagers' implementations of #inform:, #request:, #chooseFrom:, etc. a bit strange. They first signal a ProvideAnswerNotification, and then, if it was not handled and resumed, display a UI element to the user.

Why is this not rather implemented as a UserNotification, similar to the implementation of ParserNotifications? Pseudocode:


"Client code"

UIManager default inform: 'Carpe Squeak'.

UserNotification signal: 'Carpe Squeak'. "of course, we could also move this to Object >> #inform: again"

UIManager default chooseFrom: (1 to: 10).

UserNotification signalChoiceFrom: (1 to: 10).

UserNotification signalRequest: 'What's your name?' initialAnswer: Utilites authorName.


"Implementation"

UserNotification >> defaultAction

Project current uiManager inform: self messageText


UserNotification >> signalChoiceFrom: values "optional, for convenience"

^ UserChoiceNotification signalFrom: values


UserChoiceNotification >> signalFrom: values

^ self new

values: values;

signal


UserChoiceNotification >> defaultAction

^ Project current uiManager chooseFrom: self values


MorphicUIManager >> inform: aString

self askForProvidedAnswerTo: aString ifSupplied: [:answer | 
^ answer].
^ UserDialogBoxMorph inform: aString


Advantages:

  • Each notification is completely represented by a full-fledged first-class object - whereas a ProvideAnswerNotification maps the actual notification quite badly: it does not even store the values to choose from, an initial answer, etc...
  • Not only, but particularly in tests: You could do amazing things such as
  • self
    should: [ modelUnderTest doSomeOperation ]
    raise: UserChoiceNotification
    withExceptionDo: [ :notification |
    self
    should: [ '*file*exists*' match: notification messageText ];
    should: [ notification values includes: 'overwrite that file' ] ].
  • Instead of the hardcoded resumption values for canceling (#cancel and true), you could just implement #cancel on UserNotification and say:
    [ self chooseFrom: #(one two three) ] on: UserNotification do: #cancel
    • (By the way, these hardcoded values currently lead to a strange behavior of the following snippet:
      UIManager default chooseFrom: #(true false) ]
      valueSuppressingMessages: #('*') "returns 1 instead of 0")
  • Currently, we have massive duplication of calls to #askForProvidedAnswerTo:ifSupplied: in each UIManager. If we inversed the call chain as proposed, UIManagers could refocus on their task to display UI elements.
  • Maybe this change would allow us to move all the convenience methods with default parameters from UIManager into the special UserNotification classes, to tidy up the things a bit :)

Disadvantages:
  • Compatibility issues: (How) could we preserve the behavior of all current clients that directly call UIManager?
  • Add yours here :-)


Best,

Christoph



Von: Squeak-dev <[hidden email]> im Auftrag von Jakob Reschke <[hidden email]>
Gesendet: Samstag, 2. November 2019 17:36 Uhr
An: The general-purpose Squeak developers list
Betreff: Re: [squeak-dev] [Discussion] Warning vs. Halt (or: "Why is a warning a notification?")
 
Marcel Taeumel <[hidden email]> schrieb am Sa., 2. Nov. 2019, 13:54:
Hmmm..... Notifcations that claim to be resumable but require user input in #defaultAction feel kind of awkwardly designed...

Yes they are. After all they don't really have a default value that should be automatically determined. Or in other words they must be handled and if they are not they force you to handle them manually. In that regard they behave more like Errors, which are manually handled in the debugger. They are not errors from a functional perspective though.

In that sense, I can also resume any error with "nil" (or "false") if I want to....

...which is what you get when you press "proceed", right? But you are not allowed to send #resume or #resume: to them.

#resume with default value does not make much sense for those request exceptions either.

A more sensible pattern might be:

    value := RequestNotification signal.
    value ifNil: [self showUiRequest].

But you cannot enforce it anyway.

Also these requests are mostly UI situations which want to be unit-testable and therefore use these exceptions, aren't they? So they might not be amenable or relevant for catch-all exception handling for server purposes anyway.


Carpe Squeak!