Data-oriented programming models a problem as simple, explicit, preferably immutable data and expresses behavior as standalone functions over that data. In its full form, it commonly avoids encapsulation, inheritance, and internal state. The practical aim is predictable logic, easier testing, and clearer reasoning about state. section 4.2
A data-oriented approach applies this emphasis without requiring a wholesale change of paradigm. Start by asking what information the code actually manipulates, then make its structure reveal the problem: a physical profile, a weight with a unit, a range, a category, or a short-lived result. Let operations follow that model rather than hiding meaning behind generic objects and boilerplate. section 4.0 section 4.2
Make constructor intent visible
`new User("John", 180, 70)` leaves two numbers unexplained. A model such as `PhysicalProfile("John", WeightInPounds(180), HeightInInches(70))` exposes what each value means at the call site. The added types earn their place when they prevent ambiguity or communicate an important unit or rule; they are unnecessary when they merely add ceremony. section 4.0 section 4.3
Use the approach as a design heuristic, not a universal prescription:
- Model data before behavior, identifying identity, state, units, ranges, categories, inputs, derived values, and values that belong together. section 4.3
- Name data precisely and replace generic structures when a domain type makes intent visible. section 4.3
- Keep validation near the data it protects so invalid states fail early, and prefer immutability when change is not needed. section 4.3
- Use small carriers for meaningful composites, units, ranges, categories, and results; use explicit closed categories rather than free-form codes. section 4.3
- Flatten unnecessarily deep structures, but skip a new abstraction when it adds complexity without clearer understanding or protection. section 4.3
Before making changes, identify the data the code is really manipulating. Ask: - What is the central data concept? - Which values represent identity, state, unit, range, or category? - Which values come from outside the system, and which are internal? - Which values are temporary, derived, or persisted? - Which values drive behavior? - Which values naturally belong together? - Which values are part of a public contract or generated model that cannot be changed directly?
Use these questions to identify the central data concept before choosing types, validation, and behavior. section 4.3
Modern concise data constructs make this style practical in object-oriented code: Java records, Kotlin data classes, C# records, and Python dataclasses reduce supporting noise around small immutable carriers. Java records can also validate or transform values during initialization, while pattern matching can make routing by data shape clearer. section 4.4 section 4.4
The reusable rule is simple: make the data model explain the problem, then organize behavior around it. Favor precision only when it improves readability; clarity and simplicity must overlap. section 4.2 section 4.3

