An invariant is a condition that must remain true for a value or data structure to be valid. Keep rules that protect validity close to the data they govern, so invalid states are rejected early rather than discovered through scattered checks. section 4.3
In data modeling, invariants clarify intent without requiring every value to become a new type. Use explicit structures when they prevent ambiguity or invalid combinations; avoid abstractions whose complexity obscures the model. section 4.3
Flag the data model when you see any of these signals: - primitive types (`int`, `double`, `String`, `boolean`) used for domain concepts - numeric values without an explicit unit - several parameters of the same type that can be swapped at the call site - generic names: `data`, `value`, `type`, `flag`, `status`, `info`, `payload` - mutable fields where mutation is never needed - collections exposed without protection - validation rules scattered far from the data they protect - nullable fields with no documented meaning - boilerplate (getters, setters, equals, hashCode) that buries the actual structure A signal only justifies action if the change earns its place. Skip the change when: - the existing name is already clear - the value has no rule, unit, ambiguity, or risk of confusion - the type would be used only once and adds no protection - the abstraction is more obscure than the primitive it replaces - it only moves complexity elsewhere
Use these warning signs to find invariants that need better protection, especially validation scattered far from the data, exposed collections, ambiguous primitives, and unnecessary mutability. section 4.3











