John Von Neumann contributed one of the primary metaphors of computing—a sequence of instructions that are executed one by one. This metaphor permeates most programming languages, Java included. The topic of this chapter is how to express the behavior of a program. The patterns are:
- Control Flow—Express computations as a sequence of steps.
- Main Flow—Clearly express the main flow of control.
- Message—Express control flow by sending a message.
- Choosing Message—Vary the implementors of a message to express choices.
- Double Dispatch—Vary the implementors of messages along two axes to express cascading choices.
- Decomposing Message—Break complicated calculations into cohesive chunks.
- Reversing Message—Make control flows symmetric by sending a sequence of messages to the same receiver.
- Inviting Message—Invite future variation by sending a message that can be implemented in different ways.
- Explaining Message—Send a message to explain the purpose of a clump of logic.
- Exceptional Flow—Express the unusual flows of control as clearly as possible without interfering with the expression of the main flow.
- Guard Clause—Express local exceptional flows by an early return.
- Exception—Express non-local exceptional flows with exceptions.
- Checked Exception—Ensure that exceptions are caught by declaring them explicitly.
- Exception Propagation—Propagate exceptions, transforming them as necessary so the information they contain is appropriate to the catcher.
Why do we have control flow in programs at all? There are languages like Prolog that don’t have an explicit notion of a flow of control. Bits of logic float around in a soup, waiting for the right conditions before becoming active.
Java is a member of the family of languages in which the sequence of control is a fundamental organizing principle. Adjacent statements execute one after the other. Conditionals cause code to execute only in certain circumstances. Loops execute code repeatedly. Messages are sent to activate one of several subroutines. Exceptions cause control to jump up the stack.
All of these mechanisms add up to a rich medium for expressing computations. As an author/programmer, you decide whether to express the flow you have in mind as one main flow with exceptions, multiple alternative flows each of which is equally important, or some combination. You group bits of the control flow so they can be understood abstractly at first, for the casual reader, with greater detail available for those who need to understand them. Some groupings are routines in a class, some are by delegating control to another object.