Welcome to This Week in D! Each week, we'll summarize what's been going on in the D community and write brief advice columns to help you get the most out of the D Programming Language.
The D Programming Language is a general purpose programming language that offers modern convenience, modeling power, and native efficiency with a familiar C-style syntax.
This Week in D has an RSS feed.
This Week in D is edited by Adam D. Ruppe. Contact me with any questions, comments, or contributions.
See more at the announce forum.
The D exception class hierarchy does not start with Exception. The base class is actually Throwable, with two child classes: Exception and Error. Why is this?
Subclsses of Exception are meant to signify a recoverable runtime problem. A function throws an exception when it cannot complete the operation you asked it to do, but has reason to believe that a solution may exist further up the call chain, that the rest of the program is still able to function normally. For example, a file copy function may throw a subclass of Exception when the filesystem prohibits the copy. The calling function may reasonably try again and expect success later. The programmer did nothing wrong, the execution environment just wasn't able to comply at this time. The fact that the function may throw is part of its public interface.
An Error subclass, on the other hand, indicates that something is potentially wrong with the whole program and recovery ought not be attempted. If the function detects a bug in itself caused by programmer error (such as through a failing assert or an array bounds violation, both events which the programmer is supposed to ensure never happen and thus indicate a bug), it may throw an Error. These are *not* intended to be caught and are *not* part of the function's public interface. Thus, a nothrow function may still throw Error subclasses - nothrow promises no Exceptions, not no program termination. Error is simply an implementation detail of a dying program. They also bypass the normal exception chaining system - an Error goes to the head of it and stacked Errors will kill the program.
Since Error is an implementation detail of death, catching an Error, while allowed, is not guaranteed to succeed and you should not attempt to recover from it. At best, you can just attempt last-minute logging or cleanup as the program terminates. Of course, the same applies to the superclass, Throwable, which is only guaranteed to be recoverable if it happens to be an Exception object rather than an Error. (Catching Throwable is convenient if you want to do generic logging though)
A common question is: if I cannot recover from Error with catch, how can I write a program that will stay up reliably? The answer is to put your program inside a larger system with redundancy built in. For example, have the operating system automatically restart your program if it is terminated. This way, the termination cleans the broken state and the automatic restart keeps the service running. If it is very important, you will also want to have a backup server running a fallback application - ideally, a *different* fallback application, so it will not share the same bugs that led to the error in the first place. (Similarly, if you want a backup against a fire with paper files, you wouldn't want two copies of the documents in the same box because if one burns, odds are the rest of the box is burning too! You'd want to keep the backup copy in a different location so the odds of both catching fire at once is lower.)
There's no such thing as a reliable individual program. All programs have bugs, or are on computers that may lose power or suffer any number of other programs. But it is possible to build a reliable system out of imperfect, unreliable parts. Write your program as well as you can, then build a reliable system around it using concepts like redundancy to ensure the thing as a whole still delivers.
To learn more about D and what's happening in D: