P28 · Objects & Data Modelling
classes, dataclasses, the data model & protocols
Data modelling and contracts for serious Python: dataclasses done right, protocols versus inheritance, and abstract base classes as designed interfaces.
A dataclass is not a shorter way to write __init__. Used deliberately, it is
where you decide which objects are allowed to exist at all — and that decision
is worth more than any amount of downstream validation, because a check you
remember to perform is a check someone will eventually forget. This pillar is
about designing types whose invalid states cannot be constructed, and contracts
that a checker rather than a convention holds callers to.
The first track models the data. Dataclasses with the options that matter —
frozen for immutability where mutation buys nothing, ordering and comparison
where they are meaningful, defaults that do not silently share state — and
validation placed at construction, so an instance that exists is an instance you
can trust. The second track handles the interface between components, and it
turns on a distinction Python supports in both directions. Structural typing
says anything with the right shape qualifies, which is what a Protocol
expresses and what lets you accept objects from code you do not control, tests
included. Nominal typing says a class must declare its intent by inheriting,
which is what an abstract base class expresses and what lets you refuse
accidental conformance. Neither is the default answer; the track is about
knowing which question you are in.