Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
| From | Don Y <this@isnotme.com> |
|---|---|
| Newsgroups | comp.lang.c |
| Subject | Re: Mechanism to generate annotated "error codes" |
| Date | 2012-03-06 11:21 -0700 |
| Organization | Aioe.org NNTP Server |
| Message-ID | <jj5kif$ld0$1@speranza.aioe.org> (permalink) |
| References | <jiojq3$3cm$1@speranza.aioe.org> <17KdnUKUw7zqucvSnZ2dnUVZ_uSdnZ2d@posted.internetamerica> |
Hi Gordon,
On 3/6/2012 7:51 AM, Gordon Burditt wrote:
>> I have a suite of projects that utilize a common approach to
>> error reporting. Instead of a PASS/FAIL result, most functions
>> return information regarding the nature of the "failure" (which
>> can also include "partial failures"... "warnings"). These
>> reports allow upper levels of the application to convey those
>> details to the user without exposing all of the *mechanism*
>> involved to those upper levels.
>
> One approach I've seen used in BSD's libcom_err is to have different
> library modules that can each register their own blocks of error
Different environment. That tries to accommodate an open-ended
error space that is dynamically reconfigurable.
Imagine if you didn't know what ERANGE was until run time?
> codes. Any module can take one of the error codes (which it doesn't
> necessarily recognize) and call the equivalent of strerror() to
> come up with a text message to describe the problem to the user.
> There isn't really a concept of "severity" of an error code but you
> could add that. You don't need a centralized location with a full
> list of all the error codes.
To clarify (in case you haven't read the rest of the thread):
I don't want a DEVELOPERS MAINTAINED "centralize location with a
full list of all the error codes". I.e., I don't want developers
having to coordinate which "code" is assigned to which symbolic
error name.
But, *I* (which might not be a requirement for others employing
such a system) want to be able to CENTRALIZE the messages associated
with those individual error codes so that, e.g., they need not be
part of the executable images. And, so that they can be embellished
without constraint (if I want to write a 5 page description of a
particular error code -- including examples and remedies -- I should
be free to do so *if* I have a way of storing that <somewhere>)
> Along with this comes the need to
> vary the error message depending on the language of the user.
Yes. Note that the actual *nature* of the user can be addressed
with this, as well. E.g., you might have a "locale" called "devel"
which provides messages specifically designed for the development
environment containing details that a "real user" would neither
be interested in nor capable of comprehending.
Likewise, your "user" might be another process on the other end
of a network connection. Reporting "Relay denied" puts a significant
decoding burden on the (remote) "caller" whereas "550" requires very
little overhead and conveys the exact nature of the problem!
> You
> probably do need to assign a (unique) name for a block of error
> codes, which might be the name of the library or subdivision of it.
>
> There's a problem with this approach alone. A *good* description of
> the error needs variable parts dependent on the situation.
Yes. As I have stated, I have chosen to ignore this in this discussion
as it just adds another level of detail that doesn't substantially alter
the problem.
[I'm eliding most of that related discussion, here]
>> E.g., the application may need a numeric value from the user
>> with a particular set of constraints (must be positive, less
>> than 293, no more than two decimals, etc.). Of course, it would
>> be silly for the upper levels of the application to process
>> individual characters to assemble such a "value" and enforce
>> those constraints.
>
> The prompt should probably indicate the range of acceptable values
> (which doesn't excuse you from range-checking what the user types).
> What constitutes a valid number shouldn't have to be repeated
> endlessly.
This is something that the application decides -- not related to
"error reporting".
>> For example, the lower level routine might report:
>> - invalid character encountered
>> - value below minimum allowed
>> - value exceeds maximum allowed
>> - too many significant digits
>>
>> The "invalid character" report might be embelished:
>> - only one decimal point allowed
>> - only one *sign* allowed
>> - non-digit encountered
>
> "Only one decimal point allowed" might be more correctly reported
> as "multiple numbers should be separated by commas" in a situation
> where multiple numbers are a legitimate possibility.
The whole point of this is to illustrate how context influences
how an error is reported. An "upper layer" -- one that might be
expecting two values separated by a delimiter -- invokes get_value(),
twice. *It* sees "Err_TooManyDecimalPoints" returned from the
first invocation. It's possible that the user has entered two
values with no intervening whitespace *and* no delimiter. Or,
just typed "123..456". OTOH, if the same error is returned on
the second invocation, the expecation is that this was SUPPOSED
to be a single value -- we've already seen the "first" of the
two values!
How that upper layer interprets this error AND WHAT *it* REPORTS
is up to the code in that layer. Each layer interprets errors
reported to it IN ITS OWN CONTEXT and decides how to report
that "situation". The easy way out is just to relay the
error message handed to you. That's how things were done in the
1970's :>
But, that error message was created by something (the "underling")
that had no knowledge of the context in which the report is being
conveyed to the user! I.e., get_value doesn't know that there are
*two* values expected! So, anything that get_value could conceivably
report can't account for that possibility (without being foolish!)
// get first value
result = get_value(... &msg);
if (result == Err_TooManyDecimalPoints) {
printf("Have you forgotten a delimiter between values?")
break;
}
// verify and skip over delimiter
...
// get second value
result = get_value(... &msg);
if (result == Err_TooManyDecimalPoints) {
printf("A value can only have one decimal point.")
break;
}
> At some point, diagnosing the input in excruciating detail makes
> you look silly (and often wrong).
The problem is that you don't want to have to embed all of the
knowledge of every possible condition in the upper layer. E.g.,
it could reparse the input string (Gee, didn't get_value do that
already?) and notice "###..###" vs. "###.###.###" and *guess*
that the latter is more likely a missing delimiter case while
the former is probably a keybounce. But, that defeats the
purpose of hiding detail in the get_value layer.
>> Etc. The information conveyed by each of these allows the
>> application to inform the user of the exact nature of the
>> "problem" -- instead of just resorting to a "bad value"
>> report.
>
> Make sure that the user can get out of the error situation in a
> reasonable manner. For example, if the user has been repeatedly
> entering an out-of-range age for a child he wishes to enroll, perhaps
> it would be appropriate to back up and let him change his previous
> answer to "Do you wish to enroll another child?" which he read as
> "Do you have another child?" from YES to NO. (He said YES, tried
> to enter the age for his baby, then realized they were only asking
> for children old enough to enroll in this school, so the correct
> age of his baby is an error.) A CANCEL button on a popup asking
> for a set of information can be useful here.
Different issue entirely.
>> Each possible "report" needs a mechanism through which the
>> caller can ascertain the nature of the error. You *could*
>> impose a convention that causes reports to be more easily
>> summarized: e.g., 0 for SUCCESS,<0 for errors,>0 for
>> warnings (so, if you don't care about warnings the caller
>> would test for any "not negative" result codes as being
>> "acceptable" -- as in the case of SUCCESS or "too many
>> significant digits").
>
> The direct caller of a routine such as "input an integer" routine
> probably has to know the range of acceptable values (which it has
> to pass to the input function) and may need to know about a few of
> the specific error codes it can return.
But, you could craft the "get_integer" routine to be parameterized
with min_value and max_value -- so that *it* does the range checking
and just reports the result of those checks to the caller. This
cleans up the calling code and ensures values are consistently
checked.
>> That approach is fine for "small" functions with a limited
>> number of potential "results". But, consider how you would
>> scale it to more comprehensive functions. E.g., the complete
>> UI. Managing these "enumerations" gets to be tedious and
>> error prone. "Which *values* have been assigned? What is
>> a good value to pick for this new 'condition'? etc."
>
> This is the reason for suggesting that each routine have its own
> block of error codes, without worrying too much about "wasting"
> them. For example, libcom_err gives a block of 256 error codes
> to each routine. If it needs more, it can use two blocks.
> Since there are 2^23 blocks, running out should not be a problem.
"Famous last words" :>
Why do you need error codes to be contiguous? What happens when you
can't assign all of the error codes in a contiguous range? (a library
grows and needs a 257th error condition).
You don't want error codes (CONDITIONS!) to be considered a scarce
resource. That puts pressure on you to conserve error codes.
(when you've used up 240 codes in your block, don't you think
the developer starts hedging his use of NEW codes -- just so he
doesn't have to get another block?)
You see this sort of thinking every day. People want to "pre_allocate"
a block of part numbers for the various subassemblies in the product
they are designing. Or, want to assign employee numbers based on
what department they are working in. Or...
Have <something> assign a number (i.e., "representation") that hasn't
been used, yet. Record that choice (this is what liberr does -- except
it does that at run-time). When you need another "number", take
whatever that <something> gives you -- which might bear no resemblance
to the thing you were given for your previous request!
Let machines deal with the tedium of tracking which department
employee 00004 works in or where subassembly 234887 is used.
Or, what "Err_TooManyDecimalPoints" means!
>> One approach to ensuring unique "values" for each of these
>> "results" is to synthesize them from the function/file name
>> and line number where they are detected (instantiating a
>> macro at that particular point). This ensures that values
>> are unique while hiding the *actual* value from the developer
>> (*I* surely don't care if TOO_MANY_DECIMAL_POINTS resolves
>> to 0x27 or 0x7732!).
>
>> The problem then becomes one of making that information available
>> to other *consumers*! I.e., wrapping it in a header file that
>> others can reference.
>
> Each module provides its own header file, which would include:
> - prototypes for functions in the module you can call.
> - data types used by those functions
> - A list of possible error codes generated by those functions.
>
> You'd have to include that header file anyway for the function
> prototypes if you use that module whether there are error codes
> included or not.
This requires the error codes to be known at compile time.
Forces them to be "constants" (since the header file is
a string of "constant characters"). *And* requires every
processing unit to have its own header file! I.e., if
get_value throws Err_GetFoo and put_value throws Err_PutFoo,
it is possible that get_value might be included in a link
while put_value is not! (you've used up an error code
that could have been used by something else!)
>> A "solution" also needs to address the problem of *explaining*
>> the "result" (to the ultimate user). The point at which the
>> result is "signaled" contains the most information about the
>> nature of the "problem" being reported though it is in a
>> very narrowly defined context: i.e., you can tell the user
>> "Multiple decimal points encountered" -- though you can't
>> indicate the role that the value being entered plays in the
>> application (is this a person's wages? the weight of a
>> newborn child? the average lifespan of a male tortoise?).
>
> "Multiple decimal points encountered" is equally an error regardless
> of what that value represents.
But in one case, the application knows the user is specifying
an infant's weight. Instead of an impersonal, generic "too many
decimal points" message (which is what get_value would report),
the application can say "The infant's weight can contain at most one
decimal point".
This acts as an interlock with the user reassuring him that
the application is in lock step with his actions.
Or, alerting the user to the fact that he is NOT where he
thinks he was! "Whaddya mean, 'infant's weight'? I thought I
was typing in my password!!"
> The prompt for the value should indicate the data being requested,
> and the units of it. That weight of a newborn child is in *grams*,
> not ounces, which might explain the complaint about the number being
> too small, and the average lifespan of a male tortoise is in
> *years*.
Again, that is an application specific issue. If the input is
coming from a file, the application isn't "prompting" the filesystem
"OK, now I need the tortoise's age, in years please. Great! Now
the infant's weight -- in grams..."
>> So, the developer should be able to tie the explanation/commentary
>> *to* the (symbolic) result code where the result code is defined
>> instead of having to do so "somewhere else" -- hoping to keep the
>> explanations in sync with the symbolic names, etc.
>>
>> A code fragment with such a system might look like:
>>
>> if (*ptr == '.') {
>> if (decimalPointEncountered == TRUE) {
>>
>> MakeErrorCode(Err_TooManyDecimalPoints,
>> "Multiple decimal points encountered.",
>> "Only a single decimal point is allowed in numeric
>> values."
>> )
>
> You forgot here to include the string that had too many decimal points,
> and, perhaps, which file and which line it was on.
As I said at the start, I am not returning "data" to the user in
this discussion.
FILE/LINE/func are handled by MakeErrorCode -- so the developer doesn't
need to deal with that "detail". Note that all of the information
provided to and generated by MakeErrorCode is passed "out of band".
All the caller needs is a *handle* that:
- tells him that this was an error (not a warning, etc.)
- tells him *which* error it was (if he wants to take remedial action)
- tells him how to find more information about the error
The mechanism is lightweight, from the developer's standpoint.
He doesn't have to "do" much to use it or take advantage of the
features that it provides.
>> result = Err_TooManyDecimalPoints;
>> } else {
>> decimalPointEncountered = TRUE;
>> }
>> }
>> ...
>> return (result);
>
>> Obviously, a macro could #define Err_TooManyDecimalPoints to a unique
>> value, here (e.g., __FILE__ ## __LINE__). A script could parse the
>> output of the preprocessor extracting all lines of the form
>> "#define Err_" to build a suitable header file. And, another
>> script could extract the short and long textual explanations of
>> the error itself.
>>
>> I currently do this with a mix of ad hoc measures. As such,
>> it is very fragile (and an annoying drain on my time!). I'm
>> hoping for suggestions that might lead me to a better/different
>> approach (WITH THE SAME GOALS). Pointers to tools better suited
>> to this. *Or*, examples of similar approaches!!
>
> GNU gettext also deals with extracting messages from source
> code with the intent of having them translated for multiple
> languages. You might take ideas from this, or decide you need
> to use it for internationalization.
Back to comp.lang.c | Previous | Next — Previous in thread | Find similar | Unroll thread
Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-01 12:48 -0700
Re: Mechanism to generate annotated "error codes" Willem <willem@toad.stack.nl> - 2012-03-01 21:29 +0000
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-01 16:53 -0700
Re: Mechanism to generate annotated "error codes" William Ahern <william@wilbur.25thandClement.com> - 2012-03-01 14:13 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-01 22:07 -0700
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-01 17:53 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-01 23:05 -0700
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-02 01:50 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-02 00:43 -0700
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-03 17:58 -0500
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-04 03:16 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 13:47 -0700
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 13:45 -0700
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-04 18:37 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 22:12 -0700
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-08 01:41 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-09 14:34 -0700
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-02 00:30 -0700
Re: Mechanism to generate annotated "error codes" Keith Thompson <kst-u@mib.org> - 2012-03-02 02:05 -0800
Re: Mechanism to generate annotated "error codes" Kaz Kylheku <kaz@kylheku.com> - 2012-03-02 10:47 +0000
Re: Mechanism to generate annotated "error codes" gazelle@shell.xmission.com (Kenny McCormack) - 2012-03-02 14:18 +0000
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-02 10:46 -0700
Re: Mechanism to generate annotated "error codes" James Kuyper <jameskuyper@verizon.net> - 2012-03-02 14:08 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-02 12:38 -0700
Re: Mechanism to generate annotated "error codes" Kaz Kylheku <kaz@kylheku.com> - 2012-03-02 22:57 +0000
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-02 17:14 -0700
Re: Mechanism to generate annotated "error codes" Kaz Kylheku <kaz@kylheku.com> - 2012-03-03 02:25 +0000
Re: Mechanism to generate annotated "error codes" James Kuyper <jameskuyper@verizon.net> - 2012-03-03 06:10 -0500
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-03 16:12 -0500
Re: Mechanism to generate annotated "error codes" Keith Thompson <kst-u@mib.org> - 2012-03-03 04:04 -0800
Re: Mechanism to generate annotated "error codes" Kaz Kylheku <kaz@kylheku.com> - 2012-03-03 15:05 +0000
Re: Mechanism to generate annotated "error codes" Ben Bacarisse <ben.usenet@bsb.me.uk> - 2012-03-03 16:25 +0000
Re: Mechanism to generate annotated "error codes" Shao Miller <sha0.miller@gmail.com> - 2012-03-03 16:26 -0500
Re: Mechanism to generate annotated "error codes" Keith Thompson <kst-u@mib.org> - 2012-03-03 13:40 -0800
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-03 12:03 +1300
Re: Mechanism to generate annotated "error codes" Keith Thompson <kst-u@mib.org> - 2012-03-02 15:45 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-02 17:18 -0700
Re: Mechanism to generate annotated "error codes" blp@cs.stanford.edu (Ben Pfaff) - 2012-03-02 15:08 -0800
Re: Mechanism to generate annotated "error codes" "BartC" <bc@freeuk.com> - 2012-03-03 10:30 +0000
Re: Mechanism to generate annotated "error codes" James Kuyper <jameskuyper@verizon.net> - 2012-03-03 06:19 -0500
Re: Mechanism to generate annotated "error codes" Phil Carmody <thefatphil_demunged@yahoo.co.uk> - 2012-03-03 15:15 +0200
Re: Mechanism to generate annotated "error codes" Kaz Kylheku <kaz@kylheku.com> - 2012-03-03 14:52 +0000
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-03 07:39 -0800
Re: Mechanism to generate annotated "error codes" Jonathan Leffler <jleffler@earthlink.net> - 2012-03-03 23:56 -0800
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-05 09:20 +1300
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-04 13:28 -0800
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-05 10:56 +1300
Re: Mechanism to generate annotated "error codes" "BartC" <bc@freeuk.com> - 2012-03-03 17:02 +0000
Re: Mechanism to generate annotated "error codes" Keith Thompson <kst-u@mib.org> - 2012-03-03 12:30 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 19:15 -0700
Re: Mechanism to generate annotated "error codes" Kaz Kylheku <kaz@kylheku.com> - 2012-03-04 03:20 +0000
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 11:03 -0700
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 16:31 -0700
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 23:04 -0700
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-02 22:13 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 00:49 -0700
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-03 03:32 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 12:04 -0700
Re: Mechanism to generate annotated "error codes" Lowell Gilbert <lgusenet@be-well.ilk.org> - 2012-03-03 15:06 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 14:38 -0700
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-03 12:15 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 16:51 -0700
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-04 14:08 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 15:56 -0700
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-03 03:45 -0800
Re: Mechanism to generate annotated "error codes" Lowell Gilbert <lgusenet@be-well.ilk.org> - 2012-03-03 14:11 -0500
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 13:03 -0700
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 12:32 -0700
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 15:04 -0700
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-04 11:09 +1300
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 16:55 -0700
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-04 13:04 +1300
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 18:24 -0700
Re: Mechanism to generate annotated "error codes" Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-03-03 14:30 -0800
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-03 17:06 -0700
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-05 10:09 +1300
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 16:03 -0700
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-05 13:26 +1300
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-04 22:21 -0700
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-05 20:46 +1300
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-05 10:54 -0700
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-06 10:02 +1300
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-05 16:09 -0700
Re: Mechanism to generate annotated "error codes" "BartC" <bc@freeuk.com> - 2012-03-06 10:54 +0000
Re: Mechanism to generate annotated "error codes" Ian Collins <ian-news@hotmail.com> - 2012-03-07 07:22 +1300
Re: Mechanism to generate annotated "error codes" gordonb.8sa24@burditt.org (Gordon Burditt) - 2012-03-06 08:51 -0600
Re: Mechanism to generate annotated "error codes" Don Y <this@isnotme.com> - 2012-03-06 11:21 -0700
csiph-web