A Philosophy of Software Design
H. S. Teoh
hsteoh at qfbox.info
Sat Jun 27 19:44:07 UTC 2026
On Sat, Jun 27, 2026 at 07:17:11PM +0000, tony via Digitalmars-d wrote:
> On Sunday, 24 May 2026 at 01:42:43 UTC, Walter Bright wrote:
> > The first sentence of the chapter "Define Errors Out Of Existence" says:
> >
> > "Exception handling is one of the worst sources of complexity in
> > software systems."
> >
>
> Ignoring errors definitely reduces complexity, and seems to be the
> choice of a lot of people who don't like to use exceptions.
The correct understanding is to reduce complexity by rephrasing your
problem such that the number of exceptional cases is minimized.
Unfortunately, real world problems are messy and will never be
completely free of exceptional conditions. The question then becomes,
how do you handle those exceptional conditions in such a way that
minimizes the amount of complexity added to handle them?
> But if someone is going to attempt to handle or report errors, how
> does exception handling make that process more complex than passing
> return values?
IMO it's situation-specific. Expanding the domain and range of your
function to include exceptional cases as part of "normal" operation,
such as sqrt() returning NaN for negative arguments (instead of throwing
an exception, say), can reduce complexity in some ways (you don't have
to worry about catching exceptions every time you call sqrt()). OTOH,
it merely shoves the problem elsewhere: now you cannot rely on your
values being real values: NaN poisons all subsequent calculations and
now downstream code has to worry about what to do if the input is NaN.
E.g., sqrt() is involved in some calculation that eventually ends up as
the dimensions of some on-screen object. Now your rendering code has to
deal with the problem of how to draw an object with NaN dimensions.
(Complexity added: an extra NaN check in render() to prevent it from
going off the rails when it tries to loop from 0 to NaN. Or extra NaN
checks somewhere in-between to prevent it from getting into the render
queue and reaching the render function in the first place. Either way
you haven't eliminated complexity, merely shoved it into a different
form which has to be handled elsewhere.)
Sometimes throwing an exception *is* the least complex way to deal with
the problem. In opening a file, for example, instead of throwing an
exception, you *could* return a dummy object in place of a file if the
file doesn't exist, or the filesystem is corrupt, or some other error
occurs. Yes you got rid of a throw statement, but at what cost? Now
downstream code has to deal with a dummy file object. Does it continue
processing it as a normal file of 0 size? What if the program needs to
differentiate between "file not found" vs. "filesystem is corrupt"?
What if an empty file is valid input, and you need to differentiate that
from an error condition? Somewhere down the line, *somebody* has to
deal with the exceptional condition somehow. A single throw statement
is less complexity than a bunch of special code to differentiate between
an empty file and a dummy file representing an error state.
T
--
In order to understand recursion you must first understand recursion.
More information about the Digitalmars-d
mailing list