This post documents one rule of thumb I find useful when coding:
Being a rule-of-thumb, it naturally has exceptions, but those are relatively few. The primary context here is application development. Libraries with semver-constrained API have other guidelines — the rules are different at the boundaries.
This privacy rule is a manifestation of the fact that the two most popular kinds of entities in programs are:
- Abstract data types — complex objects with opaque implementation which guard interior invariants and expose intentionally limited API to the outside world
- Data — relatively simple objects which group a bunch of related attributes together
If some fields of a type are private, it can’t be data. If some fields of a type are public, it can still be an ADT, but the abstraction boundary will be a bit awkward. Better to just add getters for (usually few) fields which can be public, to make it immediately obvious what role is played by the type.
An example of ADT would be
FileSet from rust-analyzer’s virtual file system implementation.
This type maintains a bidirectional mapping between string paths and integral file ids.
How exactly the mapping is maintained (hash map, search tree, trie?) is irrelevant, this implementation detail is abstracted away.
Additionally, there’s an invariant:
paths fields are consistent, complimentary mappings.
So this is the case where all fields are private and there’s a bunch of accessor functions.
An example of data would be
This type specifies a set of paths to include in VFS, a sort-of simplified gitignore. This is an inert piece of data — a bunch of extensions, include paths and exclude paths. Any combination of the three is valid, so there’s no need for privacy here.
This rule is very mechanical, but it reflects a deeper distinction between flavors of types. For a more thorough treatment of the underlying phenomenon, see “Be clear what kind of class you’re writing” chapter from Alexandrescu’s “C++ Coding Standards” and “The Expression Problem” from ever thought-provoking Kaminski.