[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Enhanced Error Reporting / OOC Library and Locales
This isn't an answer to Eric's proposal, but rather a supplement. I
would like to address a topic that is closely related to localization,
and which is not implemented to my satisfaction in the current OOC
library. I am talking about error reporting, which plays a very
prominent in the I/O modules.
I want to propose a different error reporting interface, that
increases the usability of this part of the I/O library, and is more
powerful than the existing implementation.
The current situation: I/O operations return an error code of type
INTEGER. The code can be mapped to a string by invoking the
appropriate `ErrorDesc' method or function. The result code
`Channel.done' signal successful completion of a operation.
The list of disadvantages is long. The basic I/O modules (derived
from Channel) and Riders share the same error code space. Clashes
between numbers can happen. Propagation of error codes along a chain
of stacked channels is impossible, which makes stacking of channels
very hard. Mapping of code to strings is non-trivial, because there
are many `ErrorDesc' methods and functions. For example, `File.New'
delivers a result that is interpreted by `Files.ErrorDesc', while
`ReadBytes' delivers a result that must be passed to the rider object.
Maintaining the `ErrorDesc' procedures and the code mapping is a pain,
because this must be done at several places in any `Channel' module.
Localization is non-existant, as is Unicode support.
Proposal: Error messages are instances of a general class `Message'.
Functions return a message object in case of an error, and NIL
(=Channel.done) after successful completion. Error messages are
mapped to strings by calling an appropriate method of the error
object.
I used this model in the XML parser, and I am very satisfied with the
results. Messages are implemented by the module `XML:Msg' and have
these properties:
o Every message has a context object. Conceptionally, it describes
the module (or part of the module) that created the message.
o A message has a numeric id, that is unique within its context, but
not necessarily unique across the module, library, or program.
The ID describes the kind of message. In this context it would be
the error code of the I/O operation.
o An arbitrary number of attributes can be attached to a message.
An attribute is a (name, value) pair. The name is a CHAR based
string, and `value' can be an integer, a string (both 8 and 16
bit), or another message. Additional types of values are
possible.
o A message is converted into a readable representation by calling
its method `GetText'. This gets a template string from the
message's context object through `context.GetTemplate'. The
string can contain references like `${name}', which are replaced
by the textual representation of the named attributed.
The features listed here are implemented by `XML:Msg', which can serve
as a baseline for further discussions.
Localization can be easily added in `context.GetTemplate'. Error
objects can be passed around without restriction, because every
instance carries its own context and can create a textual
representation of itself. Mapping between error (or message) codes is
centralized at a single place in every module. The error reporting
interface is the same across all I/O function, there is no longer a
difference between `Files.New' and `TextRider.Reader.ReadBytes'.
Implementing this would mean to change the interface of all I/O
modules, but I believe this would be an excellent investment for the
future.
-- mva