Skip to main content

Explicit Outcomes and Observable Behavior

What this concept is​

An operation contract includes returned outcomes, state changes, failures and visible effects. Comparing only final state can hide incompatible behavior. An explicit result distinguishes a valid request that is rejected from malformed input.

Why it matters here​

Module 1 already teaches failure-state preservation. Now compare two implementations using the same client-visible observations. The comparison must be broader than a shared implementation helper that can repeat the same bug.

Concrete example​

An inventory begins with 3 units. Taking 2 returns Taken(remaining=1) and a new state of 1. Taking 2 again returns Rejected(available=1), leaving the state unchanged. Taking zero raises ValueError because it is outside the operation domain. In the lab, the complete operation returns (new_state, outcome); the original state remains usable.

The count representation and unit-token representation can be compared through (available_units, outcome_kind, reported_units). Their storage structures differ, but those observations should agree after every command. Retain earlier states and confirm that later commands do not alter them. A rejection-only implementation can preserve all state invariants while violating successful-taking behavior; positive controls matter.

Common confusion / misconception​

Equal final availability does not prove equal histories: two implementations can report different outcomes or emit different notifications. A differential check also cannot establish correctness if both implementations share a wrong rule. Use an independently stated mathematical oracle and concrete expected examples.

How to use it​

Define the observation function before the experiment. State whether errors, output, calls to dependencies and ordering are observable. In this lab there is no I/O, concurrency, crash persistence or external notification. Do not claim its sequential checks prove those properties.

Check yourself​

Why does checking only nonnegative inventory miss an implementation that always rejects? Why must equality between requested and available units succeed? Both follow from the operation contract rather than representation taste.

Mini drill or application​

Change rejection to include the requested quantity. Explain which result types, client observations and tests change, while the availability invariant stays the same. Then propose an external notification: identify the new failure boundary before adding the side effect.

Read this only if stuck​

Use selective reading from Cornell’s data types, MIT representation invariants, and Python dataclasses for their respective claims. Revisit the existing SICP reference for evaluation and environments; no full-book assignment is added. Continue with the construction clinic.