Book: A Discipline of Programming
Overview
Edsger Dijkstra’s A Discipline of Programming presents a method for developing programs hand in hand with their correctness proofs. Rather than writing code and then verifying it, Dijkstra advocates deriving programs from formal specifications by calculation, so that correctness is an inherent property of the artifact. The book’s centerpiece is a minimal language of guarded commands paired with a logical semantics based on predicate transformers, especially the weakest precondition. Through a sequence of small but revealing derivations, the text demonstrates how control structures, data handling, and termination arguments emerge from algebraic reasoning rather than intuition or trial-and-error.
The Guarded Command Language
Dijkstra introduces a tiny, structured language whose primitives are assignment, guarded alternation, and guarded repetition. A guarded alternation selects one among several commands whose boolean guards hold; a guarded repetition iterates while at least one guard remains true, choosing among enabled commands each time. By excluding arbitrary jumps and by separating enabling conditions from actions, the language isolates the essence of control and admits concise laws for reasoning. Nondeterministic choice is explicit, not accidental: if multiple guards hold, any enabled branch may be taken. This disciplined syntax supports reasoning that is independent of machine quirks.
Predicate Transformer Semantics
The book assigns each program statement S a transformer wp(S, R) that maps a desired postcondition R to the weakest precondition guaranteeing R after S terminates. Assignments, conditionals, and loops all receive algebraic definitions in this style. Fundamental laws, monotonicity, distributivity over conjunction for demonic choice, and compositionality, make it possible to conduct equational proofs. Correctness becomes a simple implication: a program with precondition P and postcondition R is correct if P implies wp(S, R). The semantics also cleanly distinguishes partial correctness (logical safety) from total correctness (safety plus termination).
Derivation as Calculation
Dijkstra treats programming as the gradual transformation of a specification into an executable form, with each step justified by algebraic laws. Starting from a postcondition that captures the problem, one computes a weakest precondition, introduces variables to express intermediate knowledge, and refines structure until a concrete program surfaces. Assertions are not decorations added after coding; they are the scaffolding that shapes the design. When choices arise, the method favors the most general solution consistent with the specification, postponing unnecessary commitments and thus preserving flexibility.
Loops, Invariants, and Termination
Loop design illustrates the calculus at its most powerful. The invariant is derived to preserve the essence of the specification across iterations, while a variant function into a well-founded set ensures progress toward termination. Guarded repetition expresses the permissible steps, and the invariant guides both the guards and the body. Because nondeterminism is admitted, one can initially design permissive loops and later restrict or structure them without losing correctness.
Nondeterminism and Refinement
Nondeterministic constructs model under-specification and implementation freedom. The semantics treats choice as demonic: correctness must hold for all possible selections of enabled commands. This yields robust programs that do not rely on hidden scheduling assumptions. Refinement is captured logically as strengthening preconditions and weakening postconditions while preserving correctness, enabling stepwise movement from abstract descriptions to efficient implementations.
Style, Scope, and Influence
The exposition is austere and calculational, emphasizing clarity and parsimony over pragmatics or tooling. The examples range from simple arithmetic manipulations to array-processing schemes, each chosen to illustrate a law or technique rather than to showcase application domains. The book’s lasting contributions, the guarded command language, weakest precondition semantics, and derivation-as-proof discipline, shaped formal methods, program verification, and refinement calculus, and they continue to influence modern specification languages and verification tools.
Edsger Dijkstra’s A Discipline of Programming presents a method for developing programs hand in hand with their correctness proofs. Rather than writing code and then verifying it, Dijkstra advocates deriving programs from formal specifications by calculation, so that correctness is an inherent property of the artifact. The book’s centerpiece is a minimal language of guarded commands paired with a logical semantics based on predicate transformers, especially the weakest precondition. Through a sequence of small but revealing derivations, the text demonstrates how control structures, data handling, and termination arguments emerge from algebraic reasoning rather than intuition or trial-and-error.
The Guarded Command Language
Dijkstra introduces a tiny, structured language whose primitives are assignment, guarded alternation, and guarded repetition. A guarded alternation selects one among several commands whose boolean guards hold; a guarded repetition iterates while at least one guard remains true, choosing among enabled commands each time. By excluding arbitrary jumps and by separating enabling conditions from actions, the language isolates the essence of control and admits concise laws for reasoning. Nondeterministic choice is explicit, not accidental: if multiple guards hold, any enabled branch may be taken. This disciplined syntax supports reasoning that is independent of machine quirks.
Predicate Transformer Semantics
The book assigns each program statement S a transformer wp(S, R) that maps a desired postcondition R to the weakest precondition guaranteeing R after S terminates. Assignments, conditionals, and loops all receive algebraic definitions in this style. Fundamental laws, monotonicity, distributivity over conjunction for demonic choice, and compositionality, make it possible to conduct equational proofs. Correctness becomes a simple implication: a program with precondition P and postcondition R is correct if P implies wp(S, R). The semantics also cleanly distinguishes partial correctness (logical safety) from total correctness (safety plus termination).
Derivation as Calculation
Dijkstra treats programming as the gradual transformation of a specification into an executable form, with each step justified by algebraic laws. Starting from a postcondition that captures the problem, one computes a weakest precondition, introduces variables to express intermediate knowledge, and refines structure until a concrete program surfaces. Assertions are not decorations added after coding; they are the scaffolding that shapes the design. When choices arise, the method favors the most general solution consistent with the specification, postponing unnecessary commitments and thus preserving flexibility.
Loops, Invariants, and Termination
Loop design illustrates the calculus at its most powerful. The invariant is derived to preserve the essence of the specification across iterations, while a variant function into a well-founded set ensures progress toward termination. Guarded repetition expresses the permissible steps, and the invariant guides both the guards and the body. Because nondeterminism is admitted, one can initially design permissive loops and later restrict or structure them without losing correctness.
Nondeterminism and Refinement
Nondeterministic constructs model under-specification and implementation freedom. The semantics treats choice as demonic: correctness must hold for all possible selections of enabled commands. This yields robust programs that do not rely on hidden scheduling assumptions. Refinement is captured logically as strengthening preconditions and weakening postconditions while preserving correctness, enabling stepwise movement from abstract descriptions to efficient implementations.
Style, Scope, and Influence
The exposition is austere and calculational, emphasizing clarity and parsimony over pragmatics or tooling. The examples range from simple arithmetic manipulations to array-processing schemes, each chosen to illustrate a law or technique rather than to showcase application domains. The book’s lasting contributions, the guarded command language, weakest precondition semantics, and derivation-as-proof discipline, shaped formal methods, program verification, and refinement calculus, and they continue to influence modern specification languages and verification tools.
A Discipline of Programming
A book presenting a systematic approach to program development based on formal methods and program derivation. Emphasizes proving correctness during the construction of programs and introduces techniques such as guarded commands.
- Publication Year: 1976
- Type: Book
- Genre: Computer Science, Formal methods, Programming
- Language: en
- View all works by Edsger Dijkstra on Amazon
Author: Edsger Dijkstra
Edsger Dijkstra, a pioneer in computer science known for his algorithms, programming languages, and academic contributions.
More about Edsger Dijkstra
- Occup.: Scientist
- From: Netherland
- Other works:
- A Note on Two Problems in Connexion with Graphs (1959 Essay)
- Solution of a Problem in Concurrent Programming Control (1965 Essay)
- Go To Statement Considered Harmful (1968 Essay)
- The Structure of the 'THE' Multiprogramming System (1968 Essay)
- Notes on Structured Programming (1970 Essay)
- The Humble Programmer (1972 Essay)
- Self-stabilizing Systems in Spite of Distributed Control (1974 Essay)
- Guarded Commands, Nondeterminacy and Formal Derivation of Programs (1975 Essay)
- Selected Writings on Computing: A Personal Perspective (1982 Collection)
- On the Cruelty of Really Teaching Computing Science (1989 Essay)