We are hiring

Assuming there’s a user is sometimes a bad idea

Squeak has a very strong (historic) assumption that there’s a(n interactive) user interface. I stumbled across another occurrence of this assumption the other day. Let’s take a look at the problem, and how to fix it.

You’ll recall that Squeak’s exceptions are resumable. As such, they’re often used as a means of notifying high level code of some interesting result in some low-level method. (Common Lisp’s condition system provides an equivalent service.) These kinds of exceptions subclass Notification. (Exceptions representing what most people understand by the term “exception” subclass Error; both Error and Notification subclass Exception.An unhandled exception propogates up the stack until it reaches the root context of the process. At this point the exception-handling system sends the exception the #defaultAction message. By default this asks the system to display a debugger, showing you that something drastic and unhandled has happened.

So far so good. You’ll note that we already have an assumption of a UI-like system, in that “pop up a debugger” implies such a thing. But we’re not going to talk about that today. (In fact, in shell-oriented scripts you’d use a CommandLineToolSet which would simply log the exception information and stack trace to stderr.)

No, today we’re going to talk about “let’s just tell the user that something’s interesting”, specifically, in the context of updating an image in a continuous integration environment.

When you load a Monticello snapshot into your image, Monticello constructs a diff between the changes in the mcz file and the state of your image. This diff contains things like “reshape this class”, “define that method”, and so on. If you load a Monticello snapshot that makes no effective changes to the system – you already have all the changes implied in the mcz file – Monticello will raise a MCNoChangesException. This isn’t an error: it’s just something interesting that happened. But MCNoChangesException‘s #defaultAction method looks like this:

MCNoChangesException >> defaultActionself inform: 'No changes'

This looks fine, but Object >> #inform: happens to ask the default UIManager to tell the user what happened. That happens to usually pop up a modal dialog. A modal dialog in a thing with no head, and no logging to indicate a problem. Hmmm.

There are several things we can do here:

Catch the notification and just resume it

Add a new shell-friendly UIManager that on an #inform: writes the parameter to stdout

The second option is really the right solution. Which is, of course, why I opted for the first: it’s a quick, easy fix that addresses my immediate concerns.

The moral of the story here seems to be that if you’re going to write a whole new programming environment, you should build “play nicely with command line scripts” in as early as possible. Otherwise, it becomes a real pain to automate anything, which makes CI and many other things a pain.