Writing business rules in plain English that translate to logic
A business rule written in plain English should translate to one Boolean formula without a committee. The discount rule below shows the habits that make that possible: named conditions with a one-line description each, one connective per clause, and brackets wherever “and” meets “or”.
The rule is (student OR senior) AND NOT expired AND (member OR coupon), five conditions. Each has a glossary description on the page: the customer has a student card, is 65 or older, the card or coupon has expired, the customer is a member, the customer presents a coupon. With those descriptions the engine's plain-language reading of the formula is a sentence a product owner can confirm or reject, and the truth table is the exhaustive version of the same sentence, thirty-two rows.
The habits that keep English and logic aligned are few. Name each condition as a statement that is true or false, not as a quantity (“over 50” becomes over_50, decided elsewhere). Write “and” and “or” one at a time and bracket every mixed group, because English has no precedence. Translate “unless” and “except” as AND NOT, “only if” as a necessary condition, and “either … or” as XOR only when “but not both” is meant. Keep negations attached to the condition they negate.
When a sentence resists translation, the sentence is usually ambiguous rather than the logic inadequate, and the two readings should be written as two formulas and compared; the equivalence checker reports the rows on which they differ, which is the question to take back to the rule's owner. The review checklist collects these points for the reviewer's side of the conversation.
Example
discount := (student OR senior) AND NOT expired AND (member OR coupon) · output
Exact checks
Truth table (32 rows)
| # | student | senior | expired | member | coupon | discount |
|---|---|---|---|---|---|---|
| 0 | FALSE | FALSE | FALSE | FALSE | FALSE | FALSE |
| 1 | FALSE | FALSE | FALSE | FALSE | TRUE | FALSE |
| 2 | FALSE | FALSE | FALSE | TRUE | FALSE | FALSE |
| 3 | FALSE | FALSE | FALSE | TRUE | TRUE | FALSE |
| 4 | FALSE | FALSE | TRUE | FALSE | FALSE | FALSE |
| 5 | FALSE | FALSE | TRUE | FALSE | TRUE | FALSE |
| 6 | FALSE | FALSE | TRUE | TRUE | FALSE | FALSE |
| 7 | FALSE | FALSE | TRUE | TRUE | TRUE | FALSE |
| 8 | FALSE | TRUE | FALSE | FALSE | FALSE | FALSE |
| 9 | FALSE | TRUE | FALSE | FALSE | TRUE | TRUE |
| 10 | FALSE | TRUE | FALSE | TRUE | FALSE | TRUE |
| 11 | FALSE | TRUE | FALSE | TRUE | TRUE | TRUE |
| 12 | FALSE | TRUE | TRUE | FALSE | FALSE | FALSE |
| 13 | FALSE | TRUE | TRUE | FALSE | TRUE | FALSE |
| 14 | FALSE | TRUE | TRUE | TRUE | FALSE | FALSE |
| 15 | FALSE | TRUE | TRUE | TRUE | TRUE | FALSE |
| 16 | TRUE | FALSE | FALSE | FALSE | FALSE | FALSE |
| 17 | TRUE | FALSE | FALSE | FALSE | TRUE | TRUE |
| 18 | TRUE | FALSE | FALSE | TRUE | FALSE | TRUE |
| 19 | TRUE | FALSE | FALSE | TRUE | TRUE | TRUE |
| 20 | TRUE | FALSE | TRUE | FALSE | FALSE | FALSE |
| 21 | TRUE | FALSE | TRUE | FALSE | TRUE | FALSE |
| 22 | TRUE | FALSE | TRUE | TRUE | FALSE | FALSE |
| 23 | TRUE | FALSE | TRUE | TRUE | TRUE | FALSE |
| 24 | TRUE | TRUE | FALSE | FALSE | FALSE | FALSE |
| 25 | TRUE | TRUE | FALSE | FALSE | TRUE | TRUE |
| 26 | TRUE | TRUE | FALSE | TRUE | FALSE | TRUE |
| 27 | TRUE | TRUE | FALSE | TRUE | TRUE | TRUE |
| 28 | TRUE | TRUE | TRUE | FALSE | FALSE | FALSE |
| 29 | TRUE | TRUE | TRUE | FALSE | TRUE | FALSE |
| 30 | TRUE | TRUE | TRUE | TRUE | FALSE | FALSE |
| 31 | TRUE | TRUE | TRUE | TRUE | TRUE | FALSE |
Plain-language reading
Beginnerdiscount is true exactly when all of the following hold:
1. at least one of student or senior is true (both may be true)
2. expired is false
3. at least one of member or coupon is true (both may be true)
In every other case, discount is false.
About the operators:
- AND is true only when all of its parts are true.
- OR is inclusive: it is true when at least one part is true, including when several are.
- NOT reverses a value: true becomes false and false becomes true.
Intermediatediscount is true exactly when all of the following hold:
1. at least one of student or senior is true (both may be true)
2. expired is false
3. at least one of member or coupon is true (both may be true)
In every other case, discount is false.
Advanceddiscount is true exactly when all of the following hold [conjunction ∧]:
1. at least one of student or senior is true (both may be true) [inclusive disjunction ∨]
2. expired is false [negation ¬]
3. at least one of member or coupon is true (both may be true) [inclusive disjunction ∨]
In every other case, discount is false.
Formal notation: (student ∨ senior) ∧ ¬expired ∧ (member ∨ coupon)
Logic diagram
The common slip
Translating “students and seniors get the discount” as student AND senior. The English “and” lists two groups that each qualify; the logic is student OR senior. The table makes the difference obvious, one TRUE row against three.
Questions
Should conditions be positive or negative?
Positive where possible (expired rather than not_expired), with the negation in the formula. Double negatives in condition names are where De Morgan slips start.
How do I handle numeric thresholds?
As threshold inputs: age_65_or_over is defined once as age ≥ 65 on the quantity age, and the rule keeps combining a TRUE/FALSE name. The engine derives the ordering between thresholds on the same quantity, so age_at_least_21 can never be TRUE while age_at_least_18 is FALSE, and a scenario or a test can give the number itself. Outside the app the same discipline works by hand: decide each threshold once, name it as a statement, and record its definition in the glossary where it can be read and checked.
Related
See also
- A review checklist for decision rules (for analysts and reviewers)
- Eligibility rules: the pattern, the usual exceptions and the tests
- Variable and its glossary description: meaning and examples
- “Unless” in a rule: AND NOT, not OR
- Necessary vs sufficient: “only if” is not “if”
- “A or B and C”: the grouping ambiguity and how to resolve it
- Discount eligibility rule: (student OR senior) AND NOT expired AND (member OR coupon)
- English to logic translation exercises with answers
Testing and rules
Generated from the Tangibool engine, semantics tangibool-semantics/1, engine 1.0.0, build . Every table, map, simplification and verdict on these pages was computed by the Tangibool engine when the site was built, and every claim was re-checked by the same exact checker the app uses. Limits are stated where they apply. © 2026 Foreranger LTD.