1 Data Oriented Programming
Data-oriented programming centers software design on explicit, precise representations of information. In Java, it means modeling “data as data”: treating domain facts as plain values that describe themselves rather than hiding them behind opaque private state and behavior. This approach doesn’t reject objects; it reframes them as tools for boundaries, lifecycle, and orchestration, while pushing core semantics into the data types. The payoff is simpler, smaller, and more comprehensible code, because meaning moves out of developers’ heads and into the program’s types and values.
The chapter illustrates this shift through concrete examples. Replacing an ambiguous String id with a UUID aligns representation with intent, erasing entire classes of illegal states and the defensive code they require. A more involved case refactors a ScheduledTask’s implicit state (fields like scheduledAt and attempts) into explicit domain data—RetryImmediately, ReattemptLater, and Abandon—making the program’s decisions readable and enforceable. By elevating representation, the code gains semantic integrity: it communicates what it is, not just what it does, and naturally reduces guesswork, bugs, and incidental complexity. Objects still play a role, but they emerge in the right places—vending, validating, and composing well-modeled data instead of encoding hidden meanings in mutable fields.
As data becomes the organizing force, design gravitates toward clear inputs and outputs, expressive method signatures, and expression-oriented implementations that switch on domain types rather than manipulate flags and nulls. This focus also deepens domain insight, revealing meaningful states (for example, differentiating ScheduledTask from FailedTask or CompletedTask) and guiding APIs that feel inevitable. While the book uses modern Java features (records, pattern matching, sealed types in Java 21), its practices remain accessible on older JDKs through conventions and lightweight patterns. The teaching style favors many small, real-world examples—including purposeful missteps—to build intuition for how better representations make code obvious, robust, and a pleasure to reason about.
Objects and how they communicate is our focus during object-oriented design
Being explicit about what a task can transition to after failing
Representing each decision as a piece of standalone data
Focusing on just the data makes us question our representation
clarifying what we’re talking about
Analyzing the data drives a deeper exploration of the domain
Summary
- Data Oriented programming focuses on representing data "as data"
- Data Orientation does not replace object orientation. The two work together
- In OOP, the interfaces between objects are primarily where we improve designs.
- In DOP, the representation of data is where we improve designs
- While OOP primarily asks “what does it do?”, DOP asks “what is it?”
- To quote Fred Brooks, “data is the essence of programming”
- The types we pick to represent data have a giant effect on our programs
- The wrong data representation allows illegal states to exists.
- The right data representation makes illegal states impossible to express
- A lot of what makes reading code hard is understanding the original author’s intentions
- DOP gets rid of “If X is set then it means…, but if Y is set then …” code ambiguities
- Use concrete data types to represent the meaning behind variable assignments
- Focusing on data leads to “Aha!” moments that deepen your understanding of a domain
- instanceOf is perfectly fine when used with data. The object rules do not apply
- Combining DOP with OOP makes your objects more descriptive and easier to understand
- Code naturally begins to “orient” around a good data model.
- Objects emerge around data in a way that feels inevitable.
- Good data models extends to how we design methods
- void, zero argument methods are an informational black hole.
- Make methods show what they do by using descriptive inputs and return types
- Each chapter in this book will work through a unique example
- All examples in this book are pulled from the real world. You’ll get to see all my mistakes
- We’ll use Java 21 throughout the book (though, you can still follow along with Java 8)
FAQ
What does “data as data” mean in Java?
It means modeling domain information as plain, explicit values instead of hiding it in private instance state. We still use objects, but the core emphasis is on clear data representations that directly communicate “what it is,” not just “what it does.”Does Data-Oriented Programming replace Object-Oriented Programming?
No. Objects remain invaluable. DOP changes where and how much we use objects: let objects enforce boundaries and manage state, but represent the rest as explicit data. It’s an additional tool, not a replacement.Why is data representation so important?
A precise representation makes code describe itself, eliminating ambiguity. When types capture real domain meaning, readers don’t need tribal knowledge or comments to infer intent—semantics live in the code, not in our heads.What’s wrong with using String id, and why switch to UUID?
String can represent anything, so it allows infinitely many invalid states for an identifier. Using UUID encodes the true domain meaning, preventing non-UUID values and removing ambiguity and error-prone checks.How does a better type choice reduce bugs and boilerplate?
When the representation only permits valid states, illegal states can’t be constructed. That eliminates defensive code (preconditions and if-checks), reduces tests for those guards, and makes the whole codebase smaller and clearer.What is “semantic integrity,” and how do we achieve it?
Semantic integrity means the code consistently enforces the domain’s meaning. We achieve it by modeling meanings as explicit data types (e.g., retry decisions) rather than implicit combinations of fields (like nulls and counters) that different parts of the code might interpret differently.How does the scheduled task example demonstrate DOP?
Instead of settingscheduledAt and attempts in opaque ways, we model outcomes as data: RetryImmediately, ReattemptLater, and Abandon under a RetryDecision type. The method sets a single, explicit status, and downstream code can reason directly about the meaning.Is using instanceof acceptable here?
In typical OOP, widespread instanceof suggests missing polymorphism. In this book’s DOP context, we’re operating on data representations, not behavior-rich objects, so using instanceof to discriminate explicit data variants is acceptable (and later chapters justify this fully).How does orienting around data change API and method design?
APIs become expressive and intention-revealing, e.g.,static RetryDecision reschedule(FailedTask). Methods take data as input and return data as output, favoring expression-oriented code over imperative field-twiddling. Objects naturally become pipelines that transform data shapes.
Data-Oriented Programming in Java ebook for free