liveBook · Manning

Exception

As explained in The Art of Code

An exception is a runtime event representing an abnormal condition that interrupts ordinary program execution and can be propagated or handled.

An exception makes failure explicit when ordinary execution cannot continue. Treat that failure path as part of the design, not a patch after the successful path: decide whether an operation succeeds, fails, or recovers, and release any files, connections, or sockets before it ends. section 2.5 section 7.0

Exceptions are especially awkward inside functional pipelines. A thrown exception is a side effect that interrupts the expectation of a predictable output for every input. In Java, checked exceptions such as IOException must be handled; unchecked runtime exceptions may avoid that compiler complaint but still rupture the pipeline. section 6.3.2

Make a file-read failure an explicit result

Rather than letting a stream explode while reading files, isolate the risky operation in a named method and return a ReadResult containing either content or an exception. The pipeline can then map filenames to valid outputs, while the boundary between file I/O and the rest of the flow remains visible. section 6.3.2

List<ReadResult> contents = filenames.stream()
   .map(filename -> {
     try {
       List<String> content = Files.readAllLines(Path.of(filename));
       return new ReadResult(Optional.of(content),                       #1
         Optional.empty());        #1                                     
     } catch (IOException e) {
       return new ReadResult(Optional.empty(),    #2
         Optional.of(e));                         #2
     }
   })
   .toList();

This version catches IOException at the file-read operation and models both content and error as explicit fields of a ReadResult. section 6.3.2

Handle exceptions according to the kind of failure and the audience for the outcome:

  • Keep protected blocks narrow and avoid generic catches unless there is a clear justification; a small boundary makes the failure path readable. section 7.3
  • Translate low-level technical failures at architectural boundaries into meaningful domain exceptions or controlled responses, while preserving the original cause for diagnosis. section 7.3 section 7.1.1
  • Do not show raw stack traces to end users. They can reveal filesystem paths, hostnames, SQL queries, and other internal details; provide an understandable response instead. section 7.1.1
  • Log only when it adds diagnostic value, with useful context and without sensitive data; route production logs to collection, persistence, and monitoring outputs. section 7.3

Not every failure deserves the same response. Business-rule violations, technical problems, programming bugs, and fatal errors call for different strategies. A useful heuristic is to make anticipated failure explicit, keep implementation details from leaking across boundaries, and choose recovery or propagation deliberately. section 7.3 section 7.1.1

How The Art of Code covers it

How deep it goes
Explains pipeline interruption, local catching, explicit result wrapping, exception translation, stack-trace safety, and logging practices.
Examples
Uses Java file-reading streams with IOException, ReadResult and Optional, plus a Haskell Right/Left comparison.
What it assumes
Assumes familiarity with Java streams and file I/O while explaining checked IOException behavior in the pipeline example.
What you can do after
Evaluate/understand when to catch, transform, log, or expose a failure without leaking raw technical details.
How it connects
Connects exceptions with functional programming, side effects, Optional, result types, stack traces, logging, and domain exceptions.

Also explained in

Compare how 25 books explain exception →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Art of Code. The section links point to the parts of the book it draws on.