[comp.unix.wizards] friendly messages

dhesi@bsu-cs.UUCP (Rahul Dhesi) (02/17/89)

In article <1430@X.UUCP> john@frog.UUCP (John Woods) writes:
>Then they showed an example of The New Wave, a four-line
>error message which took 3 lines to misdiagnose the problem, and reminded
>you that this was, in fact, an error.  Yup.  Just like VMS... :-)

Hmmm...I hope they don't take it too far.

TODAY (cryptic, confusing, not reassuring at all)

   $ xyz=test_symbol; export xyz
   $ sh
   $ ^D
   $

TOMORROW (warm, friendly, reassuring)

   $ xyz=test_symbol; export xyz
   %SHELL-I-SUPERSEDE, previous value of XYZ has been superseded
   %SHELL-I-EXPORT, of XYZ has been exported
   $ sh
   %SHELL-S-SPAWNED, process SHELL_002 spawned
   %SHELL-S-ATTACHED, terminal now attached to process SHELL_002
   $ ^D
     Process SHELL_002 logged out at 16-FEB-1989 11:11:16.41
   %SHELL-S-RETURNED, control returned to process SHELL_001
   $

I'm not kidding.  I actually did "define xyz test_symbol", "spawn", and
"logout" at the VMS prompt and saw roughly the above.

Here's what I would REALLY like to see:

     $ dir
     %DIR-Q-AREYOUSURE, you asked for a directory, are you sure [y/n]: y
     %DIR-Q-VERYSURE, you said yes, but are you REALLY sure [y/n]: y
     %DIR-Q-REALSURE, are you REALLY REALLY sure [y/n]: y
     %DIR-F-JUSTINCASE, no directory, say PRETTY_PLEASE
     $ dir/pretty_please
     %DIR-I-OHWELL, ok, well, if you insist
     %DIR-S-UASKED4IT, but we warn you, you did ask for it
     [ directory listing appears here]
     %DIR-I-DIRDONE, directory listing done, control returned to CLI
     %CLI-I-WHEW, *whew*, thought DIR was going to take over system
     $
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee}!bsu-cs!dhesi
                    ARPA:  bsu-cs!dhesi@iuvax.cs.indiana.edu

jamesa@arabian.Sun.COM (James D. Allen) (02/21/89)

In article <5734@bsu-cs.UUCP>, dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
> Here's what I would REALLY like to see:
					Really?  :-}
> 
>      $ dir
>      %DIR-Q-AREYOUSURE, you asked for a directory, are you sure [y/n]: y
>      %DIR-Q-VERYSURE, you said yes, but are you REALLY sure [y/n]: y
>      %DIR-Q-REALSURE, are you REALLY REALLY sure [y/n]: y
>      %DIR-F-JUSTINCASE, no directory, say PRETTY_PLEASE
>      $ dir/pretty_please
>      %DIR-I-OHWELL, ok, well, if you insist
>      %DIR-S-UASKED4IT, but we warn you, you did ask for it
>      [ directory listing appears here]
>      %DIR-I-DIRDONE, directory listing done, control returned to CLI
>      %CLI-I-WHEW, *whew*, thought DIR was going to take over system
>      $

This really made me laugh!  From time-to-time I've wanted to mail some
software to where_the_sun_doesnt_shine@software_vendor.  Rahul's
posting has induced me to give the net the benefit of my invective.  :-}

I only wish that superfluous dialog were the worst problem with
friendly software.  The "improved" `dir', for example, when it finally
gets around to listing a directory, will silently substitute a
*different* ("better", "friendlier") directory than the one you asked for.

Here are two examples of programs which try to be helpful, but where I
wish the programmer had called in sick the day he was going to add the
feature.

Example 1)

IBM language processors abound with self-righteous "logic".

Consider a C fragment like:
		/*
		 * Temporarily disable database updates, until
		 * the xlurg_gak module is debugged:
		 */
		#define	write(X,Y,Z)	\
			(printf("Would have written %d bytes\n", Z), Z)

This can be quite convenient.  The macro definition doesn't "use" X or
Y, but that is the intent.

IBM has a macro facility in JCL, something like:
		//FOOBAR	PROC	X,Y,Z

It's been a long time, but as I recall, typical output from `PROC' is:
	ILQJCL773P2: Fatal error, Formal argument `X' not used in `FOOBAR'

If you think about the implementation, it's clear that somewhere in
the JCL processor is code like:
		/*
		 * The `refcnt' array is of no value to *us* whatsoever
		 * but we need it for the friendly ILQJCL773P2 error.
		 */
		++refcnt[var_index];

Great concept!  A `fatal error' you have to go out of your way to
detect and which, if undetected, would harmlessly have the desired
effect (ie, none).


Example 2)

Just yesterday a friend asked me to help transfer some files from his
Mac to his new Unix machine.  First we connected a couple of wires
between pins 2 & 3 and pins 3 & 2.  Then we needed some software to
get the wires busy.  I'm sure everybody in this newsgroup could whip
that together in a few minutes but my friend had already purchased a
Mr_Everything_you_ever_wanted_to_do_with_your_serial_line application
so we double-clicked its icon.  I should have smelled trouble when I
noticed the icon had a real *friendly* smile.

We immediately got a "Password:" string safely back from the other end
of the wire.  "This will be real easy," I said.  "Unix is smart enough to
play stupid when you tell it to."  I did something like
		% stty raw -echo
		% cat -u > foobar^J
and selected Mr_Everything's "Send File" menu.  "We'll have to `kill'
`cat' from the other end, but that's harmless enough."

However, Mr_Everything was too friendly to send a *binary* file over the
wire.  It doesn't care what the data is, mind you, just whether it
recognizes the flavor of the mindless Macintosh file prefix.


Summary)

What are the reasons for this type of software "quality"?  I nominate
1) Mediocre programmers only get a low bug-to-keystroke ratio with
	`printf'-type code so they do lots of it.
2) Too often, software quality is judged by managers who are not
	real users.
3) Programmers view themselves as more intelligent then their users,
	but ignore that their intelligence will be "out of the loop"
	once the software (a tiny subset of their skill) is delivered.

Some will argue that my complaints are not caused because software is
"friendly" but because "it isn't friendly enough!"  But adding lots of
features *increases* problems whenever the features prove inadequate.
It's better to give the user a *simple* model of the software.
This is the original Unix philosophy:
	- do something simple
	- do it well
	- do it silently

Returning to the farcical version of `dir', for example, after receiving
complaints about the inane dialog, the "friendly" solution is to add
another option to `dir':

	$ dir/omit_inane_dialog
	%DIR-Q-IAMSOSAD, sure you want to omit the inane dialog? [y/n]:

Friendly software.  Just say no.

patrick@ism780c.isc.com (Patrick Curran) (02/22/89)

In response to various amusing comments about VMS's tendency to keep you
over-informed about what it's doing:
========

While I'm no great fan of VMS, I did spend a couple of years working with
it, and I really must correct the (mis)impressions that are being
generated here.

Yes, VMS's messages can be irritatingly wordy.  However, it is possible
to customize the message system to behave the way you want it to.  I
forget the precise details, but essentially there are several sorts of
messages (informational, warning, error, system?), and each message has
several components (a number, an identification of the program which
issued the message, an indication of its type, and the message itself).

It's possible to specify that you only want particular types of messages
to be displayed, and/or that you only want to see particular message
components.  Consequently, if you want nothing but UNIX-style terse error
messages (no fluff, no warnings, no informational messages) you can get
them.  If you want more, you can have that too.

(Now that I think of it, if you're from the "real hackers don't need
error messages" school, you could turn off all messages, so implementing
the ultimate in silent systems :-)

The advantage of the centralized error-message-handler is that user-
written or third-party programs can utilize its capabilities, inserting
their own messages into the database.  All (well-written) programs
therefore behave in exactly the same way.  Similar capabilities exist for
adding user-supplied help messages to the system help database, and for
accessing the command-line parsing capabilities of the CLI.

The result is a much cleaner interface; users know how to invoke
programs, how to get help while using them, and how to interpret the
messages they produce.  Sounds to me like a big win over the current
state of affairs in the UNIX world.  The sooner we implement something
similar, the sooner we'll be taken seriously in the real world where
people run applications rather than hack software.

Patrick Curran (uunet!ism780c!patrick)
INTERACTIVE Systems Corp, Santa Monica, CA. (213) 453-8649

warner@hydrovax.nmt.edu (M. Warner Losh) (02/23/89)

In article <5734@bsu-cs.UUCP>, dhesi@bsu-cs.UUCP (Rahul Dhesi) writes...
->Hmmm...I hope they don't take it too far.

This is agreed.  There is nothing more irritating than seeing:

	%BASIC-F-EXESTA, Execution of statement failed
	-BASIC-F-LETFAI, LET command failed
	-BASIC-F-RHSNOVAL, Right hand side could not be evaluated
	-BASIC-F-NOSTRING, String could not be created
	-BASIC-F-NOMEMORY, Memory allocation failure

When
	%BASIC-F-EXEABO, Execution aborted
	-BASIC-E-LETFAI, LET command failed at line 123 in GEORGE.xxx
	-SYSTEM-F-NOMEMORY, Memory exhaused

would do just as well.

It is informative and gives a clue where things died w/o going overboard.

(BTW, I have worked with a product on VMS that actually does the first thing
 whenever it encounters an error.  Guess the developers of that product
 didn't completely understand the error facilities they were using :-)

->TODAY (cryptic, confusing, not reassuring at all)
->   $ xyz=test_symbol; export xyz
->   $ sh
->   $ ^D
->   $
And totally uninformative.


->TOMORROW (warm, friendly, reassuring)
->   $ xyz=test_symbol; export xyz
->   %SHELL-I-SUPERSEDE, previous value of XYZ has been superseded
->   %SHELL-I-EXPORT, of XYZ has been exported
->   $ sh
->   %SHELL-S-SPAWNED, process SHELL_002 spawned
->   %SHELL-S-ATTACHED, terminal now attached to process SHELL_002
->   $ ^D
->     Process SHELL_002 logged out at 16-FEB-1989 11:11:16.41
->   %SHELL-S-RETURNED, control returned to process SHELL_001
->   $

I contest that this is user friendly.  It is informative, and lets you know
exactly what is going on.  Granted, there should be an easy way to globally
turn the chatter off.


->I'm not kidding.  I actually did "define xyz test_symbol", "spawn", and
->"logout" at the VMS prompt and saw roughly the above.

Ah, but if you place the following in your startup file on VMS, you can
get rid of the obnoxious messages:

$ DEF*INE :== DEFINE/NOLOG
$ SPA*WN :== SPAWN/NOLOG

(Which solves the immediate problem.)
-or-

$ SET MESSAGE/NOTEXT/NOID/NOSEV/NOFAC

Which tells the system not to bother you at all with any error messages.

[Rediculous example deleted]
This example is so rediculous, that any programmer that makes his programs
do this by default should be shot.

BUT the point is well taken:  Provide good error messages and a consistant
user interface, but please don't over do it.
->Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee}!bsu-cs!dhesi
--
Warner Losh
warner@hydrovax.nmt.edu		...!unmvax!nmtsun!warner%hydrovax
What happened to our innocence, did it go out of style?
My spelling and views are my own.  Only the letters have been changed...

stpeters@dawn.steinmetz (02/23/89)

In article <22569@ism780c.isc.com> patrick@ism780c.UUCP (Patrick Curran) writes:
>Yes, VMS's messages can be irritatingly wordy.  However, it is possible
>to customize the message system to behave the way you want it to.

Not really.  For example, if you turn off all the components, you
never get *any* error messages, which is a bit more terse than even
UNIX.  However, even if you have the messages turned off, VMS will
still inform you that you've logged off.  Rather handy, that. :-)

There are other things too.  Fortunately, I don't have to use VMS much
anymore, so I don't remember what they are, but they were once a pain.

>The result is a much cleaner interface; ...
>Sounds to me like a big win over the current
>state of affairs in the UNIX world.  The sooner we implement something
>similar, the sooner we'll be taken seriously in the real world where
>people run applications rather than hack software.

>Patrick Curran (uunet!ism780c!patrick)
>INTERACTIVE Systems Corp, Santa Monica, CA. (213) 453-8649

Well, Pat, we were once an all VMS site.  Management was a little slow
noticing that 1) most of the applications we ran were ported from
UNIX, and 2) every time they bought a VMS machine they wound up
shelling out thousands of dollars for INTERACTIVE's UNIX emulation.

Finally, they let us have real UNIX.  We've been happily running
applications ever since.  More and more the business components of GE
have been doing so as well.
--
Dick St.Peters                        
GE Corporate R&D, Schenectady, NY
stpeters@ge-crd.arpa              
uunet!steinmetz!stpeters

dave@whoops.celerity (Dave Smith) (02/23/89)

[much funny material about VMSization of Unix deleted]

This reminds me of when DEC was VMSizing RSTS/E (a PDP-11 operating system
sometimes reminiscent of CP/M).  Digital was making a push to get rid of
the old commands, like PIP, SYSTAT (similar to who) and replace them with
the Damned Command Language, which had verbose monstrosities like 
SHOW USERS/ALL.  My complaint was that commands like this were entirely
too verbose to use all the time and too easy to misspell.  DEC's answer
was that one, these verbose commands were more mnemonic and two, if you
wanted to you could abbreviate to SH US/AL.  Somehow, SH US/AL made a lot
less sense to me than SYSTAT which was mnemonic and easy to type.

Oh well, that was about the time I discovered Unix and found out what cryptic
_really_ meant!


David L. Smith
FPS Computing, San Diego
ucsd!celerity!dave
"Repent, Harlequin!," said the TickTock Man

bzs@Encore.COM (Barry Shein) (02/24/89)

>The result is a much cleaner interface; users know how to invoke
>programs, how to get help while using them, and how to interpret the
>messages they produce.  Sounds to me like a big win over the current
>state of affairs in the UNIX world.  The sooner we implement something
>similar, the sooner we'll be taken seriously in the real world where
>people run applications rather than hack software.
>
>Patrick Curran (uunet!ism780c!patrick)

You miss the whole point of Unix's terseness.

The point is that the output of one command is intended to be useful
as the input of another command, or, the terminal.

It's not a "user-friendly" issue or decision, it's a productivity
decision.  VMS doesn't have pipes and often produces output its other
programs can't read anyhow, due to the zillions of RMS file format
mismatches (even if you manage to figure out how to save it to a file,
no I/O redirection) so it's comparing apples and oranges, who cares if
it's full of "RMS-I-EVERYTHING-A-OK" messages, it's just zipping off
the screen anyhow (no piping to "more" either, lovely, user-friendly
system, zip zip zip...what was that?) It's nice to hear there's some
way to shut it up but that really begs the point (ie. the design of
VMS.)

Being as VMS never considered the output of its programs very useful
they felt free to babble whatever they wanted and generally make it
impossible to ever parse up.  In unix the designers preferred the
output of programs to be useful.

I realize people find this point aggravatingly subtle.

	-Barry "Keen Eye for the Obvious" Shein, ||Encore||

bzs@Encore.COM (Barry Shein) (02/24/89)

Cryptic is in the eye of the beholder. Consider a voice-communications
system which required you to type in 7 to 10 digit strings to
establish virtual circuits! AT&T has done fairly well with this
design, and it's not obvious that any change would be for the better.

The most amazing part of any technology are the people who use it,
be careful when playing armchair psychologist.

	-Barry Shein, ||Encore||

guy@auspex.UUCP (Guy Harris) (02/25/89)

>The point is that the output of one command is intended to be useful
>as the input of another command, or, the terminal.

Output, or error output?  The error output of commands *should* be
intended to be useful to the poor sap who's trying to use the command,
even at the expense of making it harder for some program to parse.

guy@auspex.UUCP (Guy Harris) (02/25/89)

>Cryptic is in the eye of the beholder. Consider a voice-communications
>system which required you to type in 7 to 10 digit strings to
>establish virtual circuits! AT&T has done fairly well with this
>design, and it's not obvious that any change would be for the better.

Yes, at times I've noticed the annoying similarity between the error
messages UNIX coughs up and the error messages the phone system coughs
up....  Whilst a change to the scheme for dialing may or may not
represent an improvement, other aspects of the phone system *could* be
changed in ways that, at least from the end-user's viewpoint, would be
for the better.

One example is the moral equivalent of the "syntax error" message.  You
know, the one that starts with that horrible shriek (which, I seem to
remember hearing, is required by some standard, so that one may not be
AT&T's fault), and then informs you that "your call cannot be completed
as dialed".

This is about as annoying as, say, the "foo: alpha/beta/gamma: cannot open"
messages that UNIX programs tend to cough up.  A change that is
obviously for the better is to have those messages print out the error
message associated with "errno", so you don't have to try an "ls" to see
if the file doesn't exist, or exists but doesn't let you read it, or....

The moral equivalent of such a change to the phone system user interface
would be for it to tell you something like "that call's in your area
code, dummy, leave the area code off!"  An even better change would be
for it to ignore the area code; I don't know whether either change is
possible - it may well not be, and it may be too expensive to change the
phone system to support it, and may have been too expensive to built the
phone system to support it.  The same isn't true of UNIX; using "perror",
or using "sys_nerr" and "sys_errlist", isn't that costly.

(Also, going back to the original point, consider a networking system
that required you to type in N-digit strings to specify host addresses
in individual configuration files for various network services; a change
that centralized the host-name-to-address mapping and let all the
services use that mapping, so that their configuration files could have
names, would be a change for the better.)

>The most amazing part of any technology are the people who use it,
>be careful when playing armchair psychologist.

Well, I *have* used UNIX and the phone system, and yes, there are places
in both where the cryptic error messages simply suck.  Ever tried
debugging a long "ed" script with a version of "ed" that *cannot* be
told to print long error messages? I made the SunOS 4.0 "ed" print *line
numbers* when it's in "long error messages" mode - as turned on by the
"H" command, since that "ed" is derived from the S5R3 "ed" - and was
given the "-" option.  That made it *lots* easier to debug big "ed"
scripts such as the ones used when building the S5R3 "curses" library. 

People too often seem to take it for granted that short, cryptic error
messages are ultimately a Good Thing under all circumstances and that
UNIX has nothing to learn or to improve in this regard.  It's simply not
true.  (Why did not "ed" print TECO-style short error messages instead
of just "?"?   As I remember, DEC TECO printed error messages with a "?"
followed by a 3-letter code, or maybe vice versa.  Terse, but at least
it doesn't throw away information....)

None of this is to say that VMS-style error messages necessarily
represent an improvement, just that there *is* plenty of room for
improvement in UNIX's error messages.  (At least we no longer have
botches such as "ar" printing its error messages to standard output;
well do I remember doing "ar t foo.a | lpr" and getting one sheet of
printout saying "foo.a does not exist"....)

guy@auspex.UUCP (Guy Harris) (02/27/89)

>Ah, but Guy, if the phone system were more like VMS then they'd surely
>have to charge you for unanswered calls and the like or they'd go
>broke!

I neither want UNIX nor the phone system to be "more like VMS" in that
regard.  I just want them to be less prone to withholding information
from me when reporting an error, since that information could allow me
more quickly to fix the problem they're reporting.  I also don't want to
see people equating "better error messages" with "error messages like
VMS", either when arging against better error messages or when trying to
improve them!

merlyn@ernie.Rosemount.COM (Brian Westley) (02/28/89)

>Cryptic is in the eye of the beholder. Consider a voice-communications
>system which required you to type in 7 to 10 digit strings to
>establish virtual circuits! AT&T has done fairly well with this
>design, and it's not obvious that any change would be for the better.
>	-Barry Shein, ||Encore||

It's easy to do better; phone USED to work better.  You picked up
the phone and said "John Q. Public, please" and that was all.
I bet phones will do this in the future, only you'll be talking to
a voice recognition circuit instead of a human.  It'll also know
who YOU mean if you ask for "John" or "Mom" or whomever.

Merlyn LeRoy

consult@osiris.UUCP (Unix Consultation Mailbox ) (02/28/89)

Despite the fact that a lot of people have a lot to say (or flame) on this
issue, it seems that there is really very little controversy, at least about
what error messages should say.  The consensus seems to be (correct me if
I'm wrong.. :-) that error messages should say just enough to please the
user and no more.  The problem here is (of course) defining the term "user".
The same problem exists with the term "user-friendly".  It's not possible to
lump all users of any commercial computer system into a single group with
definite and consistent interface preferences.  This applies to error
messages as well as the syntax of a command-line interface or whether the
system has a command-line at all (e.g. Mac).

In general I won't touch anything "user-friendly" with a ten-foot mouse.
This is because I personally find the typical "user-friendly" interface to
be anything but a help to software development.  I already understand the
system I am working on pretty well; I am familiar with navigating UNIX
filesystems, making system calls, predicting the effect of wildcards in
shell scripts, etc.  I don't want to be led by the hand through fifteen
nested menus to get into an editor.  I don't want to ever *have* to use a
mouse - I've been a touch-typist since long before I ever worked with
computers and because I *write text* for a living, it's much more important
for me to have my fingers on the home keys than to be able to point to a
menu selection when I'm just trying to logout.

We write applications on UNIX systems which run on UNIX systems and are
used by (largely) unskilled users.  We have to be very careful about what
our "users" see, that it is as consistent as possible between systems and
neither cryptic nor prolix.  When our programmers are called upon to
second-guess the users by predicting the acceptability of a certain
feature, they frequently get it wrong because they are looking at the
system from a completely different angle.  (We are slowly learning that
we don't have the smarts to outguess our "unsophisticated" users.)

I don't like systems that assume that I have no experience with them.  Many
other programmers that I work with feel the same.  Some don't.  Some
otherwise perfectly good programmers always have to be led very carefully
the first time through something or they won't get it.  On the other side
of the coin, some applications try to assume that the "user" knows a lot
more than they really do; most of our "users" don't like it when our systems
do this, though some do.

I think the fundamental problem here is that some people haven't yet
figured out that they are trying to make everybody happy at once, which we
know (cf. Heisenberg :-) cannot be done in reality, whatever that is.

I'll keep using UNIX as long as I can, unless I find something I like
better.  I have so far found no "user-friendly" interfaces which I find
more intuitive or productive than the Bourne shell.  If I ever do, I'll be
sure to let everyone know.  :-)


Phil Kos
Curmudgeon Supreme

jacobson@karachi. (Dan Jacobson) (02/28/89)

I remember this VMS nastiness:
%E-BUZZOFF Foreign commie terminal type.  By a DEC terminal and reenter command
-- 
Dan Jacobson, jacobson@eecs.nwu.edu, {oddjob,gargoyle,att,...}!nucsrl!jacobson

guy@auspex.UUCP (Guy Harris) (03/01/89)

>The consensus seems to be (correct me if I'm wrong.. :-) that error
>messages should say just enough to please the user and no more.

Yes.  However, one gets the impression that some programmers have a
quite bogus idea of how much this actually is - often bogusly small.  If
I have to dive into the source code to figure out what the problem is,
and then find that it's, say, some straightforward error in a
configuration file, the person who designed the error messages screwed
up.  If I have to "ls" a file to figure out whether the application
couldn't open it because it doesn't exist, or because it's not
readable/writable by me, or because it's on a read-only file system,
or..., the person who designed the error messages screwed up -
especially given that the "open" call will tell you that, so all they
had to do was *not* to throw out the information stashed in "errno"!

>The problem here is (of course) defining the term "user".

And one of the main problems is that they too often define "user" as
"wizard" - or, worse, assume that "the experienced user can" - and
*should* - "figure out what's wrong".  Even wizards sometimes get
*really* ticked off at cryptic error messages; yes, they *can* -
eventually - figure out what the problem is, but they often don't like
playing 20 Questions with the machine in order to do so.

I've been working with UNIX for over 10 years now, and I *still* find
many of its error messages to be quite poor, although they have slowly
gotten better over time - yes, I can poke at enough things and figure
out what the *real* problem is, eventually, but I'd rather *not* be
forced to do so, especially if the computer could have added some extra
bit of information to its messages that would have told me what the real
problem was immediately.

>The same problem exists with the term "user-friendly".  It's not
>possible to lump all users of any commercial computer system into
>a single group with definite and consistent interface preferences.
>This applies to error messages as well as the syntax of a command-line
>interface or whether the system has a command-line at all (e.g. Mac).

The term "user-friendly" doesn't denote very much.  It *con*notes quite
a bit, but the connotation depends on the audience; if it's some bunch
of novices, it's intended to connote Motherhood, Apple Pie, and the
Flag, and if it's some bunch of UNIX hackers, it's often intended to
connote Satan and grape Flavor-Aid.  In the former case, it can be used
to make some not-so-wonderful package sound better than it is, and in
the latter case it can be used to inappropriately dismiss some
reasonable ideas.

In other words, the issue of whether mouse-based user interfaces are
good or bad has a lot less to do with the issue of how noisy an
application might be in the face of errors that is often thought.

campbell@redsox.UUCP (Larry Campbell) (03/01/89)

Having spent the last year or so trying, among other things, to help
our customers use our software, I have developed some very strong opinions
on the subject of error messages:

    1.	Messages must be accurate and relevant.  This should go without
	saying, but the infamous "not a typewriter" message reminds me
	that it bears repeating.

    2.	Messages must be complete.  If the problem is related to
	a particular entity (file, process, device), the entity
	MUST be named.  "File not found" is useless -- you must
	tell me *which* file you were trying to find!

    3.	Messages must not be excessively scary.  Words like "illegal",
	"corrupted", "damaged" and the like should be avoided.  They
	*will* result in telephone calls which *cost* *you* *money*.

    4.	If there's anything the user can do about the error, the message
	must be understandable and must suggest a course of corrective
	action.  But if it's just a bug the user can't do anything about,
	the message should direct the user to call customer support,
	and it should display enough information so the poor support
	person has half a chance of fixing the problem.

    5.	It is better to give too much information than too little.
	You can always ignore the excess information, but when you're
	trying to support a customer six time zones away, you're going
	to want as much information as possible to be available.  Remember,
	the hard problems aren't repeatable, and even if they were, it's
	too expensive to keep a customer on the phone trying things out
	for you.

I once attended a lecture given by Ben Schneiderman (Univ. of Md.) about
human factors engineering.  He pointed out that the best error message he
knew of was the one you get when you misdial a phone number (this was before
divestiture):

	"We're sorry, but we are unable to complete your call as dialed.
	Please check the number and try your call again, or call your
	operator for assistance."

This is an excellent error message, for the following reasons:

    1.	"We're sorry,"  It starts out by apologizing!  For your mistake!

    2.	"We are unable..."  It blames itself, and not the user!

    3.	"Please check the number..."  It suggests not one, but two
	alternative courses of corrective action.

In contrast, if compter programmers had designed the message, it would
probably say something like:

	%ATT-F-INVADDR, Invalid or incomplete address, call aborted
or
	Not a typewriter

which, to the average user, would be frightening, confusing, and
almost completely uninformative.
-- 
Larry Campbell                          The Boston Software Works, Inc.
campbell@bsw.com                        120 Fulton Street
wjh12!redsox!campbell                   Boston, MA 02146

vfm6066@dsacg3.UUCP (John A. Ebersold) (03/03/89)

In article <1089@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
>>The consensus seems to be (correct me if I'm wrong.. :-) that error
>>messages should say just enough to please the user and no more.
>
>Yes.  However, one gets the impression that some programmers have a
>quite bogus idea of how much this actually is - often bogusly small.

Yes, like printing errno, instead of the error message.

On a releated topic...

How many times has anyone heard (or said) something like.  "I'm not checking
the return value becuase I can't do anything about it anyway."

To me, this is not true.  You can always print a message that says:

Horrible error in program foo, function bar, the function bletch returned a
-1 on about line x.

I'd rather have this than a mysterious failure.

-- 
John A. Ebersold  at  Defense Logistics Agency   osu-cis!dsacg1!dsacg3!vfm6066  
Unify Corporation     System Automation Center   Columbus, Ohio 1-614-238-5923
Me?  Speak for anyone else?  Don't be ridiculous!                  AV 850-5923
Systems with poorly understood requirements cannot be developed in a crunch.

peter@ficc.uu.net (Peter da Silva) (03/03/89)

Have you looked at the new "perror()" docs? They describe a 4-component
error message format for all programs to use, containing the name of the
program issuing the message, the name of the object responsible, the error
message itself, and a severity level (INFO, WARNING, ERROR, FATAL).

Like this:

	% cat /dev/dull
	cat: fatal: /dev/dull: No such file or directory

Unfortunately, they still haven't bothered to make all programs use perror()
itself! This, all by itself, would take care of the biggest problems with
UNIX error messages.

You get this:
	% cat /dev/dull
	cat: cannot open /dev/dull
	% nm /dev/dull
	nm: can't open "/dev/dull"
	% file /dev/dull
	/dev/dull:     cannot open

Doesn't exist? File not found? What?

At least they could do this:
	% more /dev/dull
	/dev/dull: No such file or directory

That's more like it.

It'd take one summer student to fix this. Sigh...
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Work: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.   `-_-'
Home: bigtex!texbell!sugar!peter, peter@sugar.uu.net.                 'U`
People have opinions. Companies have policy. And typos are my own business.

gwyn@smoke.BRL.MIL (Doug Gwyn ) (03/03/89)

In article <3283@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes:
>Have you looked at the new "perror()" docs? They describe a 4-component
>error message format for all programs to use, containing the name of the
>program issuing the message, the name of the object responsible, the error
>message itself, and a severity level (INFO, WARNING, ERROR, FATAL).
>	cat: fatal: /dev/dull: No such file or directory

perror() CANNOT do this, as its interface is standardized and has no
room for the additional information (severity and object; the program
name can and probably should be automated).  Presumably there is an
analogous function that accepts the additional information.  The specs
for this interface would be very handy; we could implement it and
start using it now, rather than having to wait a year.

Generally I approve of the extended message format and agree that it
needs to be used by (nearly) all the standard system utilities.

What is supposed to be done when there is no particular object?
	prog: fatal: ???: Insufficient memory available

gwyn@smoke.BRL.MIL (Doug Gwyn ) (03/03/89)

In article <1369@dsacg3.UUCP> vfm6066@dsacg3.UUCP (John A. Ebersold) writes:
-How many times has anyone heard (or said) something like.  "I'm not checking
-the return value becuase I can't do anything about it anyway."
-To me, this is not true.  You can always print a message that says:
-Horrible error in program foo, function bar, the function bletch returned a
--1 on about line x.
-I'd rather have this than a mysterious failure.

I agree with you in general; however, there's one common case where the
best solution seems to be to ignore the failure:  when an attempt to
output an error message (to stderr, usually) fails.  What are you going
to do, try to print yet another error message?

The "assert" macro defined by "#include <assert.h>" is very handy for
handling program logic bugs, in many cases.  Sometimes it is important
to try to recover from an error and resume normal operation, rather
than terminating the process.

peter@ficc.uu.net (Peter da Silva) (03/06/89)

In article <9780@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes:
> In article <3283@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes:
> >Have you looked at the new "perror()" docs? They describe a 4-component
> >error message format for all programs to use...

> perror() CANNOT do this, as its interface is standardized and has no
> room for the additional information (severity and object; the program
> name can and probably should be automated).

I realise this. The document describes what programs should do for error
messages, but makes no recommendation as to how this should be done.

> Presumably there is an
> analogous function that accepts the additional information.

Unfortunately it's like Open Look... they just specced what it should look
like without providing a programmer interface. The documentation has been
out in the bookstores for some time: it's a red book with a plastic spiral
binding.

> What is supposed to be done when there is no particular object?
> 	prog: fatal: ???: Insufficient memory available

What does perror do when there is no particular object?

	if(!(buffer = malloc(BUFSIZ*NUMBUFS))) {
		perror(.....?.....);
		...
	}

Same problem.

Perhaps we (the usenet community) should spec a better interface:

extern char *progname;
extern char *errformat;
extern char default_errformat[];
char *errmsg();

main(argc, argv)
int argc;
char **argv;
{
	progname = argv[0];
	errformat = getenv("ERRORFORMAT");
	if(errformat == NULL)
		errformat = default_errformat;
...
}

...
	fprintf(stderr, "%s\n", errmsg(object, severity));

errformat would be printf/sccs-like:

	%p	program name
	%P	program name, tail only (no path).
	%o	object
	%e	error message
	%E	short error message
	%s	severity
	%S	severity, 1 char
	%E	%p: %s: %o: %e
	%Q	%o: %e
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.
Work: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.   `-_-'
Home: ...!texbell!sugar!peter, peter@sugar.hackercorp.com.            'U`
People have opinions. Companies have policy. And typos are my own business.

lee@ssc-vax.UUCP (Lee Carver) (03/07/89)

In article <1369@dsacg3.UUCP>, vfm6066@dsacg3.UUCP (John A. Ebersold) writes:
> In article <1089@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
> >>The consensus seems to be (correct me if I'm wrong.. :-) that error
> >>messages should say just enough to please the user and no more.
> >
> >Yes.  However, one gets the impression that some programmers have a
> >quite bogus idea of how much this actually is - often bogusly small.
> 
> Yes, like printing errno, instead of the error message.
> 

Actually, the problem is that there is NO right level of detail.
The slickest approach I've seen is to let the user decide how much
detail to look at.  No surpisingly, this approach is well based in
cognitive psychology.

A recent CACM paper (K Efe, "A proposed solution to the problem of
levels in error-message generation", CACM, vol 30, no 11, Nov 1987,
pg 948) provides a very simple implementation.  It allows the user
to review the failed execution, and uncover the problem.  It also
starts with a good discussion of why a single error message is
inadequate.  Basically, it put the programmer in the position of
arrogantly "knowing" what the user wants.

For those without the paper, it is basically a tarceback stack in
user sensible terminalogy.  You don't have to implement all the
"what next" capability in his paper to have a useful error system.

Lee Carver
Boeing Aerospace

davidsen@steinmetz.ge.com (William E. Davidsen Jr) (03/07/89)

In article <1369@dsacg3.UUCP> vfm6066@dsacg3.UUCP (John A. Ebersold) writes:

| On a releated topic...
| 
| How many times has anyone heard (or said) something like.  "I'm not checking
| the return value becuase I can't do anything about it anyway."
| 
| To me, this is not true.  You can always print a message that says:
| 
| Horrible error in program foo, function bar, the function bletch returned a
| -1 on about line x.
| 
| I'd rather have this than a mysterious failure.

  I've done this many times. What would you do when you get an error,
for instance, writing stderr? When I detect a serious error I attempt to
output a warning message to terminal and/or files as appropriate, then
clean up as best I can. When something is seriously wrong writing error
messages, etc, can mess up additional parts of the program.
-- 
	bill davidsen		(wedu@ge-crd.arpa)
  {uunet | philabs}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me

jgp@moscom.UUCP (Jim Prescott) (03/29/89)

In article <3314@ficc.uu.net> peter@ficc.uu.net (Peter da Silva) writes:
>Perhaps we (the usenet community) should spec a better interface:

A nice quick 90% solution is a printf-like function that writes to stderr,
prepends the program name to the message, and can append the system error
message.  Something like:
	if (open(fname, O_RDRW, 0) == -1)
		errmsg("Cannot open \"%s\" for read/write -- ", fname);
would output:
	prog: Cannot open "somefile" for read/write -- Read-only file system

This makes it fairly painless for the programmer to come up with an
informative message without worrying about the little details.  Trying
to use perror to get a nice message is too much work, which is probably
why it isn't used as often as it should be.

The problems in implementing this are:
	- finding the program name; most likely needs to be stashed away
		while in main().  (It would have been nice if the ANSI-C
		folks had invented some globals to hold copies of main's
		arguments.  (I know it isn't their job to invent :-).)
	- deciding where to put the system error.  The code below tacks it
		on the end of the message iff it doesn't end in a newline.
		Not a great solution but certainly much simpler than doing
		a new % escape.

An enhancement would be introduce error levels (we use FATAL, ERROR, INFO
and DEBUG) and provide some way to specify which you want to see (we default
to FATAL & ERROR).

I've even enclosed a function to implement it below (about 99% of which is
from an article on varargs by Chris Torek).  I'm not sure how portable
vsprintf is, its on our sun but wasn't in V7 so it probably isn't universal.
If anyone can tell me where to get a pd vsprintf I'd be grateful.

While we're on the subject, Guy mentioned TECO error messages but not how
nifty they actually are.  You can tell it to print just the 3 letter code
(eg. ?FNF), to print the 1 line error (eg. ?FNF File not found.) or to print
the 1 line message followed by a couple of likely paragraphs out of the manual
(this is called "war and peace" mode).  Its flexible even if not overly
useful (I can't imagine using anything other than 1 line messages.  Maybe
the 3 letter only would be good on 110 baud ttys).

========= varargs version
#include <varargs.h>

int
errmsg(va_alist)
	va_dcl		/* N.B.: no semicolon */
{
	int	ret;
	char	*fmt;
	va_list	ap;
	char	buf[1024];		/* shouldn't be fixed size */

	va_start(ap);
	fmt = va_arg(ap, char *);
	ret = vsprintf(buf, fmt, ap);
	va_end(ap);

	fprintf(stderr, "%s: %s", Progname, buf);
	if (*(buf + strlen(buf) - 1) != '\n')
		perror("");
	return ret;
}
#endif

========= stdarg version
#include <stdarg.h>

int
errmsg(char *fmt, ...) 	/* the `...'s are part of the syntax */
{
	int	ret;
	va_list	ap;
	char	buf[1024];		/* shouldn't be fixed size */

	va_start(ap, fmt);
	ret = vsprintf(buf, fmt, ap);
	va_end(ap);

	fprintf(stderr, "%s: %s", Progname, buf);
	if (*(buf + strlen(buf) - 1) != '\n')
		perror("");
	return ret;
}
-- 
Jim Prescott	moscom!jgp@cs.rochester.edu
		{rutgers,ames,harvard}!rochester!moscom!jgp

chris@mimsy.UUCP (Chris Torek) (03/30/89)

In article <1411@moscom.UUCP> jgp@moscom.UUCP (Jim Prescott) writes:
[much deleted; these are retained in order]
>	ret = vsprintf(buf, fmt, ap);
>	fprintf(stderr, "%s: %s", Progname, buf);
>		perror("");

Beware, beware!  His flashing eyes, his floating exception!

Oops, a bit of stream of unconsciousness there.

This can produce the infamous sendmail-style message:

	Cannot exec /bin/mail: Not a typewriter

because fprintf() can call isatty() which can set errno to ENOTTY.
To fix this you should either save and restore errno, or change the
code to fish the error message directly out of sys_errmsg[], or
use strerror() (if your C library has it).
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

peter@ficc.uu.net (Peter da Silva) (03/30/89)

Neither of these solutions is correct:

In article <1411@moscom.UUCP>, jgp@moscom.UUCP (Jim Prescott) writes:
> 	fprintf(stderr, "%s: %s", Progname, buf);
> 	if (*(buf + strlen(buf) - 1) != '\n')
> 		perror("");

If this is the first time I/O is done, on at least some machines stdio
will call isatty(0) to determine if stdout should be unbuffered. It will
not save and restore errno. Your program may give such useful advice
as:

	foobar: can't open file barfoo -- Not a typewriter.

or:

	foobar: can't open file barfoo -- Inappropriate ioctl for device.
-- 
Peter da Silva, Xenix Support, Ferranti International Controls Corporation.

Business: uunet.uu.net!ficc!peter, peter@ficc.uu.net, +1 713 274 5180.
Personal: ...!texbell!sugar!peter, peter@sugar.hackercorp.com.

daveh@marob.MASA.COM (Dave Hammond) (03/31/89)

In article <1411@moscom.UUCP> jgp@moscom.UUCP posts his favorite error
message printer.

I note that for a return value it provides the return from vsprintf.
Since error message printers are typically invoked prior to a return,
or exit, I opt to have my favorite error printer return -1.

While this, perhaps, bastardizes the significance of the function's return
value, it (more often than not) makes for convenient error handling:

	...
	if (an_error_occurred)
		return(errmsg(errcode, "Can't open file %s.", fname));

Obviously this presumes that the calling function normally returns -1 as
an its error condition value.  Functions which don't employ a -1 error
return just void the return from the error printer.
--
Dave Hammond
daveh@marob.masa.com

guy@auspex.UUCP (Guy Harris) (03/31/89)

 >A nice quick 90% solution is a printf-like function that writes to stderr,
 >prepends the program name to the message, and can append the system error
 >message.  Something like:
 >	if (open(fname, O_RDRW, 0) == -1)
 >		errmsg("Cannot open \"%s\" for read/write -- ", fname);
 >would output:
 >	prog: Cannot open "somefile" for read/write -- Read-only file system

CAREful - you may want to call this function for errors that *don't*
cause "errno" to be set.  You might want to have some way to indicate
whether it should use "errno" or not - or, perhaps, just use the
(dp)ANSI C routine "strerror", which takes an "errno" as argument and
returns a pointer to the appropriate error message string, and just
stick "%s"es into the message string and calls to "strerror" into the
argument list.  (If your implementation doesn't have "strerror", it's
probably a 5-minute job to whip one up, at least under UNIX.)

 >This makes it fairly painless for the programmer to come up with an
 >informative message without worrying about the little details.  Trying
 >to use perror to get a nice message is too much work, which is probably
 >why it isn't used as often as it should be.

Yes, but unfortunately burying the call to "perror" in "errmsg" has its
own problems.  Note also that there are places other than "errno" where
errors are reported (by other packages, such as TLI, ONC RPC, database
libraries, etc.), often with their own families of error codes and messages,
so you may end up having to stick calls to the "return error message"
code in *anyway* in some cases....

jfc@athena.mit.edu (John F Carr) (04/01/89)

I include in this article a manual entry for a library function for error
reporting developed by the Student Information Processing Board at MIT.
This is useful because it allows libraries to define their own set of
error codes and messages without adding any user level error processing
code.  Library functions can return an internal error code or a unix error.
The com_err function recognizes the type of error and prints an appropriate
 message.  Each library is given its own range of error codes to avoid
conflict.

It is still possible to print useless or incomprehensible error messages
when using this library, but it encourages a consistent, hopefully good,
style of error reporting.

COM_ERR(3)          UNIX Programmer's Manual           COM_ERR(3)



NAME
     com_err - common error display routine

SYNOPSIS
      #include <com_err.h>

     void com_err (whoami, code, format, ...);
          const char *whoami;
          long code;
          const char *format;

     proc = set_com_err_hook (proc);
     void (* proc ) (const char *, long, const char *, va_list);

     proc = reset_com_err_hook ();

     void initialize_XXXX_error_table ();

DESCRIPTION
     Com_err displays an error message on the standard error
     stream stderr (see stdio(3S)) composed of the whoami string,
     which should specify the program name or some subportion of
     a program, followed by an error message generated from the
     code value (derived from compile_et(1)), and a string pro-
     duced using the format string and any following arguments,
     in the same style as fprintf(3).

     The behavior of com_err can be modified using
     set_com_err_hook; this defines a procedure which is called
     with the arguments passed to com_err, instead of the default
     internal procedure which sends the formatted text to error
     output.  Thus the error messages from a program can all
     easily be diverted to another form of diagnostic logging,
     such as syslog(3).  Reset_com_err_hook may be used to
     restore the behavior of com_err to its default form.  Both
     procedures return the previous ``hook'' value.  These
     ``hook'' procedures must have the declaration given for proc
     above in the synopsis.

     The initialize_XXXX_error_table routine is generated mechan-
     ically by compile_et(1) from a source file containing names
     and associated strings.  Each table has a name of up to four
     characters, which is used in place of the XXXX in the name
     of the routine.  These routines should be called before any
     of the corresponding error codes are used, so that the
     com_err library will recognize error codes from these tables
     when they are used.

     The com_err.h header file should be included in any source
     file that uses routines from the com_err library; executable
     files must be linked using ``-lcom_err'' in order to cause
     the com_err library to be included.

SEE ALSO
     compile_et (1), syslog (3).

     Ken Raeburn, "A Common Error Description Library for UNIX".

-------

Here is an example of its usage (from "zwgc", the main client for the
Zephyr message delivery service):

            if ( (nzqueued = ZPending()) == -1 )
              {
                if(errno == ZERR_EOF)
                  {
                    com_err("zwgc",errno," on select");
                    exit(-1);   /* if eof, we still can't exit_cleanly */
                  }


--
   John Carr             "When they turn the pages of history,
   jfc@Athena.mit.edu     When these days have passed long ago,
   bloom-beacon!          Will they read of us with sadness
   athena.mit.edu!jfc     For the seeds that we let grow?"  --Neil Peart