Skip to content

Software Quality

Decision tables

A decision table is a grid: one row per combination of input conditions, one column per condition, one final column for the decision. Writing the table forces enumeration of every case; missing rows become visible at a glance. The implementation becomes a lookup against the table. A decision table is a lightweight formal specification: it has one consistency rule, needs no notation beyond a labeled grid, and anybody can learn to read one (Wayne 2018)1.

What it catches

  • Missing rows in decision logic. Three boolean conditions produce eight rows; eligibility logic that handles seven of them ships a policy gap.
  • Inconsistent rows. Two rows that match the same inputs but prescribe different decisions are a contradiction; the table surfaces them as duplicates.
  • Dead conditions. A condition that never affects the outcome shows up as a column whose values don't change the result. Often a sign of dead code or over-specification.
  • Stakeholder ambiguity. Product, legal, compliance, ops can read a table where they cannot read source code.
  • Drift between policy and code. When the table is the source of truth, tests check the implementation against the table; any divergence is a code bug, not a policy bug.

Reviewers run these checks by eye on a markdown table or spreadsheet. On a table in DMN (Decision Model and Notation) format, dmn-check flags conflicting rules automatically.

Decision tables catch nothing outside the case space they enumerate.

Tools

The right form depends on who needs to read and edit the table.

  • A markdown table in the repo. The recommended baseline. The PR review surfaces missing rows; the table lives next to the code that implements it.
  • A spreadsheet (Excel, Google Sheets). When stakeholders outside engineering need to read or edit the table. A CSV export carries the rows back to the test suite or into a markdown doc.
  • DMN — an Object Management Group (OMG) standard for decision tables; used by rule engines and business-process-management (BPM) platforms.
  • Drools, OpenL Tablets, and Operaton: open-source rule engines that execute decision tables. Drools and Operaton run DMN files directly; OpenL Tablets runs tables written in Excel. Operaton is the Apache-2.0, community-owned fork of Camunda 7; the commercial Camunda 8 platform's DMN engine does the same job. Useful when business analysts own the rules.
  • dmn-check — static analysis for DMN files: detects duplicate, conflicting and shadowed rules and type errors in rule expressions. Runs in CI or as a Camunda Modeler plugin.
  • In-source enumerations. A typed sum type that enumerates the rows, plus an exhaustive match / switch, gives the same guarantees the table does, and the type checker enforces them.

When to use, when not

Use:

  • For any feature whose decision combines two to five conditions. The cost is minutes.
  • For regulated decisions where stakeholders outside engineering must read and approve the rules. The table is the contract.
  • When porting eligibility or pricing logic across implementations. The table is the durable artifact; the code is not.
  • As an entry point to formal methods on a team that has none. The notation is a labeled grid, nothing more.

Don't:

  • When the case space is large. Past ~5 binary inputs the table has 32+ rows and is no longer scannable; a rule engine or hierarchical decision tables handle that size.
  • For continuous conditions. A table over buckets of the range (e.g., "age < 18", "18–64", "65+") has a finite case space.
  • For control-flow decisions that have state. State machines model the states and the legal transitions between them.

Evidence

The support for decision tables is definitional, not statistical: the table is exhaustive by construction.

Exhaustive enumeration of a bounded input space, compressed several ways

These methods all exhaustively enumerate a bounded input space; each compresses the exponential blow-up a different way. Decision tables compress losslessly: a "don't-care" entry folds together combinations that share an outcome, so every case still maps to one rule, and the row carries its own expected decision. Combinatorial and pairwise testing sample: a covering array keeps every t-way interaction and drops the higher-order ones, with the oracle supplied separately. Bounded-exhaustive property testing bounds the size: it enumerates every value up to a depth/size k (SmallCheck), relying on the small-scope hypothesis that faults surface small. Exhaustive coverage runs from MCC (the full 2ⁿ truth table) down to MC/DC's n+1 independence criterion, and audits an existing suite rather than generating one. Type systems reach the same completeness by construction: an exhaustiveness check on a match / switch over a sum type has the compiler verify every variant is handled, with no case written by hand. State-, path-, and schedule-space enumerators such as model checking, symbolic execution, and systematic concurrency testing share the idea over a different space; see the reachability clusters.

Classification

  • Quality dimensions: Functionality: conformance (a regulated rule set is a declared standard, and the table is the artifact stakeholders outside engineering read and approve).
  • Area: Eligibility rules, pricing, access control, regulatory rules, insurance and tax logic, feature-flag decisions, anywhere business logic combines several conditions into one decision.
  • Guarantee: Exhaustive — by construction, no case is missing.

Referenced by

References