Debuggability by Design
A system that can answer what happened, why, for whom, on which version. Stable ids, deterministic cores, and time and randomness as injected dependencies.
A system should be able to answer what happened, why, for which request and user, on which version, and from which state. None of those are answerable later if the design did not record them.
Log state transitions and external interactions. A log line is an interface with a future reader, and most debug logging is a message the author sent to themselves an hour ago.
request_id, order_id, workflow_id. Correlation is a design decision made in the first week or not at all, because an id cannot be added to records that were written without it.
Same inputs, same outputs, every time. A domain core with no ambient time, randomness, I/O or global state can be tested exhaustively, replayed from a log, and reasoned about without running it.
A `now()` buried in a rule makes the rule untestable and unreproducible. Injecting a clock fixes that and costs a parameter threaded through code that did not want one — which is a real price, not a rounding error.
The same argument as the clock, applied to anything that returns a different answer each call: id generation, shuffling, sampling, jitter. Injected, they are reproducible; ambient, they are a bug you cannot re-run.