Skip to main content

CSE 331: Error handling and interactive programs

This lecture studies a calculator, an interactive program: one that responds to each input as it arrives, and keeps running until the user tells it to stop. Lecture 3's Sum, a batch program, stopped at the user's first mistake. The calculator must not: each mistake gets a message, and the loop goes on. So main has to learn of every operation that could not be done. The program keeps two concerns apart, a separation of concerns: main talks to the user, and CalcStack does the arithmetic and knows nothing of users. So a user's mistake arrives inside the program as a request that a method cannot carry out, such as popping an empty stack, and the method has to say no to its client, through its specification.

The calculator's stack tells main six different ways, one for each operation that can fail. A precondition makes checking the client's job. A special value, such as null, is returned only on failure, and must be a value the method never returns otherwise. A flag turns void into boolean. A wrapper, such as an OptionalInt, either holds the answer or is empty. An unchecked exception ends the method and is caught by a try in the client, or else ends the program with a stack trace. A checked exception must be caught or declared by every client, and the compiler checks that it is.

All six work when the client checks. They differ when the client forgets: a forgotten flag fails silently, a broken precondition allows anything, here a confusing exception, a forgotten null is printed to the user or stops the program at a conversion, a forgotten exception ends the program with a stack trace, a wrapper asked without a check stops the program at the ask, a wrapper used as an int does not compile, and a forgotten checked exception does not compile at all. A mistake the compiler catches never reaches a run, so when you can, let the compiler find it.

A seventh way, making up an answer, is a bad one. JavaScript's undefined, an unchecked NaN from floating point division, and a null the specification does not allow are made-up answers: each travels on into later results, so the mistake shows far from its cause, or never.

Interactive programs are harder to get right than batch ones: their state lasts across inputs and is hidden from the user, who chooses the order. Keeping that state apart from the loop that talks to the user keeps it testable.