Open Community Experience (OCX)

Data oriented programming in Java

39:38 · 21 Apr 2026 – 23 Apr 2026 · YouTube

About this talk

In this talk, Birgit, a freelancer from Germany with extensive experience in Java and Spring Boot, discusses data-oriented programming as an alternative to traditional object-oriented programming. She outlines the core principles of data-oriented programming, emphasizing the importance of modeling data purely as data, ensuring immutability, validating data at boundaries, and making illegal states unrepresentable. Birgit introduces algebraic data types, including sum types and product types, and explains how features like sealed classes and records in Java support this paradigm. She also highlights the benefits of pattern matching for enhancing data processing and provides examples of where data-oriented programming can be beneficial, such as in domain modeling and JSON parsing. The speaker concludes by encouraging developers to explore this programming style while noting its limitations in scenarios involving complex state and behavior.

Full transcript

Hello everyone. Nice to see you and I think what believe the last session of the day or full session of the day. So you're probably quite tired already and I promise I have nothing too complicated for you today. So who am I? Who's here? My name is Birgit. I'm from Germany. I'm a freelancer in the Java ecosystem. Mainly Java backend and Spring Boot and Oh, okay. for

the camera. Um I also do Spring Boot development and teach Spring Boot. So um not exactly Jakarta. Well, Spring Boot uses Jakarta. Uh I've been experienced for more than 25 years. This means also I'm getting older. And I'm co-organizing some meetups and the Socrates Germany. Have you heard of it? Yes. Very good. It's a software crafting and testing conference. or more like a community conference. In Germany.

You can apply for it. Maybe you can take part in it. It's an unconference. Quite cheap. It's always fun to be there. Okay. So we want to talk about uh data-oriented programming, but before that, before I start with that, we have to talk a little bit about object-oriented programming, what where Java is rooted, kind of, hm? So, um there there are those fundamental principles we all use

if you write code in Java, we all use all the time. Like encapsulation, meaning that we have data and we have method that act on this data. We can use inheritance, polymorphism, uh abstraction. Abstraction means that we don't give out everything we program, but we have kind of an in public interface to use uh with our data. But, um you might sometimes feel that using object-oriented principles

can also sometimes be a bit tedious in some cases. And so, there's always light and and shadow. And so, we have this light and shadow uh I I pointed out like three three points light and shadow advantages. We for with inheritance, we can have code reusability. Where yeah. But, lately I I I I think the shift goes more to not have too much inheritance and code reusability.

That's my what I experienced. But, with deep inheritance comes also this can become quite fragile. Sometimes you have that even in in test classes that you have to dig down deep because there's lots of inheritance going on. And I hate this kind of code. Uh of course, you have this intuitive modeling, you can kind of uh uh model real world entities. So. those entities are also mutable

because as of until Java, I think 15 or 16 was mainly uh classes. We have new things to to become more immutable. But, uh we talk about this later. Uh and you have, of course, separation of concerns. You can through encapsulation put stuff in different classes and only the class the classes only do uh things that they're supposed to do and they're named for and then one

class uses the other and so on. But, this can also lead to tight coupling and uh maybe it's sometimes hard to test stuff like that. So, yeah. So, where there's light, there's also shadow. That's Um so, the question is, is there a way to overcome these drawbacks somehow with maybe new language features which were introduced uh uh since I think Java uh 16, which is always already

like 5 years or something, no? Uh but, can we maybe combine these these uh new developments into something more suitable in certain cases? before I come to that, we have to talk algebraic data types. And now you say, "What? Algebra? Well, I That's not what I thought of. So, what is uh What is an algebraic data type and why is it important for data-oriented programming? Um an

algebraic data type is um actually a composite type. And there more more or less two types, a sum type and a product type. The names are a bit confusing in my mind. Maybe we can rename them in or and end which which they're also called. So, let's have a look at what are these uh sum types or or types or product types or end types? And now

I confused you. Uh so. Let's start with sum type. What is a sum type? It's It It actually um gives you choices. Uh that you can define different values. Uh and and only one value can be true at any given time. I give an example in a shape. Uh can be a triangle or square or a rectangle or a circle as I said here. Uh so, I

have the choice. It's either or. One or the other. Uh and I can give I can like predefine the choices. If I want to have more choices, I have to define them somehow. So, this is uh Can someone think of um Java representation of such an or type or sum type? Enum? Exactly. This is uh This would be Yeah. An algebraic data type is some type. Okay.

Any other idea about what could be a some type? With a new language feature, maybe a JDK something. Sealed classes. Yeah. Sealed types. This is It came into Java with JDK 17. And uh sealed types uh is you can have sealed classes or sealed interfaces. And what you do is um you say which classes can implement for for instance in sealed interface. And only those classes are

allowed to implement this interface. And no other classes permitted to do And this uh is a good information for the compiler. It It knows an an infinite amount of classes can by definition. So, how how do you write this? It's just a You just uh use the keyword sealed before the interface. And then after the the name of the interface, you say uh permits circle, rectangle, uh

or triangle. And only those three types can implement this interface shape. No other types. If I wanted to have more types to in to to implement this interface, then I have to state this. And as I said, the compiler can work with this kind of information. Keep this in mind. So, now, the product type. This is a type that uh is a Yeah, contains values of of

other of Yeah, of other the the whole combination of these types is the value of this I said here, "According to this definition, any immutable class that only holds data fields but provides no methods to alter to alter this data can be considered a product type." What would this be in Java? With new Java language features? Record. Exactly. We had this before in in the talk. what

is a record? A record would was also introduced in It was already introduced in Java 16. interfaces was Java 17. actually it carries immutable data. uh which data it carries uh at the point of instantiation of the record. And I can't change the data afterwards, even not with uh reflection. Of course, if the data is a list, I could change the content of the list. This is

still possible. But only Yeah. Can I do that? No. Can't reflect into it. I can't set it afterwards. No, maybe not. It's Yeah, you have maybe have to try. But uh this is perfect for modeling data. So, for for just and and I can be sure these data are stable and and immutable. So, they can flow through my program and don't have any side effects. This is

a guarantee. So, now we have our records uh rectangle, circle, triangle with certain parameters uh which which I need maybe to calculate What what is it called the content of of a circle? What What's this in English? Not the the the area. Exactly. now we have these uh um sealed classes or sealed interfaces and and uh records identified I as algebraic data types. Okay, so what what

can I do with What would be the answer? What What does it help me? I mean, I can I have now immutable data and I have sealed classes or a sealed interfaces, but where is it interesting to use? the answer for that is as we just had in the in the talk before is pattern matching. Pattern matching has um it's it's it's a mechanism where I can

de-structure data and bind data to variables and then extract those data. And and Essentially it. I can then compare is is something of a type is something a certain value and so on so on. And so pattern matching has several behaviors. It tests if something is has a certain structure. It I can it can bind this structure to a to a variable or it and And it

looks like looks for exhaustiveness. Ensure that all cases are covered. Remember our sealed classes. We have an of classes that can can be of a certain And I can also give guardrails a circle can never have a negative radius something like that. So I can give some guardrails. We just had uh one instantiation of this pattern matching and for Java it was the instance of. We just

learned about it for primitive with instance of I can now uh say instead of the instance of is already an uh thing I think we had before in Java before we already had to cast. Later on we said is is it an instance of and if so, then cast it to that type and now we can write something like We don't have to cast anymore. And then

S is valid within the bracket I just experimented with it and I could also say if it is not S, then I can use the S of also outside of the bracket. It's quite quite a nice feature. And what kind of instance what kind of do we do we have in Java? It's another type of pattern matching. It's quite new since Java 21. Can you think of

anything? Pattern matching of for for switch. match over over the the shape for instance, because it's an interface and all the instances are all the instances of shape, I can pattern match. And I can say, "Okay, is is shape a rectangle? Do this. Is it a circle? Do do something else." Here I calculate the area and here you also see as with the instance of, I can

bind it to a variable. Like rectangle R and then I can drill into this rectangle kind of uh call the the parameters inside the rectangle. another way to do this is if is when I use a pattern matching another pattern matching it's the record patterns additionally to that. So I I don't have to define the the variable R for a rectangle, but I say, "Okay, the rectangle

has two parameters and I can kind of bind them here already and immediately use them. This is quite a nice feature. Sometimes I this this one is maybe sometimes more readable. Here, But then there there are other jobs in JDK 22 came the unnamed variables. So if I don't need one of the variables here, I just say, "Okay, underscore." I don't even have to care about it.

Or as we just heard, primitive type in will come also. algebraic data types and we have pattern matching and yeah. So what can we do with it? And here comes the data oriented programming into play. So how can we use it? What is actually data oriented programming? This follows like four principles. And the first principle is model data as data and nothing but data. So, don't use

but just model your data. Period. Don't In inside those data classes, don't do calculation methods or something. Don't put this into the data classes. Just The second principle is data is We just heard records are immutable. You could use that. third principle is validate at the boundaries. So, if you instantiate a record, you only instantiate one that is valid. And you can't put in in invalid data.

You can cannot put in. You can do that with with records in in the constructor that you say, "Okay, for instance, circle negative radius values are not allowed. If there's negative coming in, I throw an exception." Okay? the fourth point is make illegal states unrepresentable. This is also like validate at boundaries kind of, but also like uh sealed sealed classes or sealed interfaces, I cannot check any

anything else but what is allowed. I have uh I have some kind of type safety on and and and and and also instance safety. I cannot check more than is this is allowed. And also the compiler would help me uh if I add another another type that is allowed with a and I used these uh sealed interface somewhere in switch cases, the compiler would tell me, "Ah,

you have to handle this case in the switch case." It will point me to uh the the area where I have to do the correction or the addition. And I Otherwise, it wouldn't compile. Under certain circumstances. So, now we we look at those four points in detail. Um Model the data, the whole data, and nothing but the data. I just model it my my interface and all

the the instances I can have or the permitted classes I can have implement the the interface. I could have a shorthand writing. Uh say sealed interface and not not permits anymore, but inside the interface, I say, "All these records are permitted." This is uh the same as the one before. Then, data is immutable. We talked about records. use records more. I often see it at uh the

the the people write uh uh class and then only getters for it. Why? Use a record If you use Java 16, 17, use a record. It also helps with the concurrent problems in concurrent text context because the data is stable. You can just give it to another thread. So, what? Cannot change it. And you don't have any hidden side Validate at the boundaries. I talked about this.

So, you can uh mhm have an um constructor inside your record which validates input data. You could probably validate before that, before you even instantiate a record, but latest point is here. And I already said that make illegal So, um the compiler ensures that all shape variants are handled, but only if you don't use default the default branch. So, uh maybe try to avoid the default branch.

Then, if you change the the the shape interface in in some way, the compiler will tell you, "Hey, here in this switch case or in that switch case, you have to handle this This additional case. So, those are the four principles of data-oriented programming. Quite simple. I have some examples for you. Two examples. Uh one is the state machine for order processing. You could say, okay, order

state like pending, confirmed, shipped, delivered, and so on. And then I define records for each state. With some data inside which are important to for that state. then what's a tracking number then some payment IDs or cancellation date and the reason why it was cancelled and so on and so on. So this is the data part. Nothing more here. Just data as data and And then you

have maybe a class that processes these data and there you have those switch statements. Maybe you want to get a status message for each state. And then you say, okay, all the cases I have and then write out a status message. And you see no default here. If you would invent an an additional state and put it in the in in the data here, then the compiler

would say, okay, you have to do it do something here as well. This is the status message or you could also say something confirm order. Then you put in the state and the payment ID and it says, okay, if the state is pending, then I can confirm it with some data. create a new state. Confirmed is already confirmed, so just give it back. Everything else cannot be

confirmed. Or something like So, I want to check if I can cancel in a certain state and I say, "Okay." Uh pending and confirmed, yeah, you can cancel. Everything else, you can't cancel. Before that, um think about how you would write this kind of code before you had uh records, pattern matching, for records and and all pattern matching in this or and before sealed interfaces and sealed

classes. This would be quite some logic you have to write. and now, you would have like uh an abstract order state and then implementations of it and then you would have uh transition logic from one state to the other and many code points you have would have to touch. And if you invent a new state, you have many code points to touch, but the compiler doesn't help

Okay. Another one is um JSON parsing parsing without pattern or recursion. Again, starting with with the data model, and here, you have like uh um JSON can be a string, a number, a boolean, null, or an array, or an object. And inside the array and object, you already see there there we have some um recursion there. There's also JSON value inside this one. recursive usage usage of

of the model, so to say. And then again, processing this data, you can again have a JSON processor and just write out maybe JSON uh uh string. you have in in the last case my fingers are not in the JSON object you have again a stringify call stringify method again. So, this is kind Which always twists my brain if I have to write it without this kind

of syntax. Or you can say find me something within a path. This is a lot of code, don't read it. Maybe it doesn't work. I don't know. But you see you can it's always the same thing that you have case switch cases handle those different cases within the in the switch cases. And not much code really. And in the old ways certainly have to have some recursion

method then. One calling the other and and some uh jump out logic when to stop and so on and so on. And this is all quite crisp code, I think. Good to read. And um yeah. Just nicer. And if you are happy enough to already use Java 21, you can do all that. when is um data-oriented programming useful? Is it a new hammer for all our problems?

Um okay, there there is some some areas where it is useful and and you can easily use it and other areas where it's maybe not that useful. Useful areas is like domain modeling as we have seen with those two examples. or you can think of financial systems or medical records, anything where you can data and those those are the primary source of of your of your logic

and or configuration data. Uh you where you need type safety and clear clarity of the data are the driver of of of your Uh data transformation pipeline. Something comes in and you want to transform it into something else. Like ETL processes, extract, transform, load. Easy peasy. All this uh just data here, data there and transform it. APIs for data and data transfer. Uh so, APIs are they

nowadays with microservices or I don't know whether whether microservices still a thing or the small services. Uh API data, they they can be modeled as records easily because they come in and you don't want to change them because that's what the customer sends you. Maybe you want to store it but or you want to uh transfer it somewhere else. But there you have your data and then

you can say okay, whatever comes in I can handle with records and and maybe and and sealed sealed interfaces. In concurrent systems, of course, we have immutability built in in our algebraic problem domains, it says like expression evaluators, abstract syntax trees, state machines, I showed you this maybe game logic, something like that. So that those are the the fields where you could use data-oriented programming. uh have

to use like visitor patterns recursive methods, which I said always twist my brain. I don't know how about you. Maybe some some people like writing stuff like Not me. So I already asked is it is it the hammer for all our problems now? Do you know the hammer factory story? Yeah, okay. of course not. It's not the hammer for all of problems. So when do to stick

to So if if your state and behavior is tightly coupled, you stick to it. Stick to orient object-oriented programming or like uh if you have complex behavior or stateful processes and so on, then then data-oriented programming is not not the ideal solution, I would say. or when Yeah, lots of state change over time and so on and so on. You have to think about data-oriented programming is

useful here or if you stick to object-oriented Uh Data-oriented programming is really useful for smaller systems, like I already told you, like data-centric business logic, compilers, parsers, whatever you have in your systems or you need. And maybe have a hybrid approach. It depends on on what you do. Maybe part of it can be data data-centric and the other part is more object-oriented. That's but with with the

new features in Java, you have the possibility to do both. And you should use it. I think the hardest part is to define in a good way. But when you do like domain-driven design or this already gives you the model. So, that's all I have for you today. Any questions? Uh thank you for that. That was very interesting. Um I have a question about how null analysis

relates to this. So, like on slide 23, you have the switch statement, you know, that has circle or triangle, and it says like, you don't need a default, you don't have But there's there's no nulls checking in your example, and I'm just wondering how your experience of Like, what do you do to make sure that we don't have to have that extra complication in here? Since shape

can be >> think there will be a pattern match for null soon. Yeah. Um maybe this helps, and otherwise Yeah, maybe you have to to check the null before the switch. For now. But do you find in practice that like using null analysis is an idea to do in in situ- like I just your experience of of how you handle null in your It's about like, do

you just do you use null analysis, or you just do null checks in the code? Probably mostly null checks so far. Um there are new ways like those those not nullable annotations you can define the What's what's this little library called? I think in Spring they use it quite a lot now. The way you can say um you can tell the compiler here what comes in here

must not be null. And if there is a possibility that it is null, the compiler will already cry. And if you don't have that, or if you don't use that, yeah, you have to do some kind of null check. But with um yeah you could also also uh instantiate them with values of null, yeah. You have to check that probably. But um there will be I think

there there will be a pattern match for uh um or a switch pattern matching for null soon. So so then you just add null into the switch case in that case. And the case null and then do this and that. Yeah. They're working on it. Um I have some resources for you. I I I will upload the the uh slides. and there is some some good I

mean this this data-oriented programming uh um stuff is is not quite new. Brian Goetz already talked about it in 2021, I I think it has not been talked about enough. So it's quite a nice uh paradigm.