Layout of Domain Modeling book
This is an episode of Thoughts on Functional Programming, a podcast by Eric Normand.
In this episode, I talk about the three parts of my book, which mirror the three levels of domain modeling.
[00:00:00] What is the layout for my new domain modeling book? That's what I'm gonna talk about today in this episode. My name is Eric Normand, and this is my podcast. Welcome.
[00:00:18] So you might notice there's some background noise. I'm trying out my old style format again. Uh, it was getting hard to get in the groove doing a recording in my little studio, so I'm in the car again, and now that I have a commute again, I thought I would use this time to talk and to record ideas and try to make it more off the cuff.
[00:00:49] And, just really raw because I want to think out ideas. So right now [00:01:00] I'm working on my book and I thought it would be cool to lay out the main structure and talk about why I broke it up that way. So the book is divided into three parts. It's about domain modeling. The working title is domain model.
[00:01:19] There's three parts that correspond to three different levels of domain modeling. So one of the problems you, when you have a big topic like this is you have to put it into some kind of linear order, and you really want everyone to know everything all at once, and they can. You gotta start somewhere. And so then where do you start?
[00:01:47] Well, you have to start. with the most concrete thing first. And what is the most concrete thing? Well, it's data modeling. [00:02:00] Data modeling is actually very concrete and most people probably already know how to do it decently. Especially people who work with something like J, they know how to represen.
[00:02:15] Entities or other concepts in their domain as data structures, like named, named attributes named, uh, references nested things. And that's data modeling. But I, I wanna give it a more precise definition. But before I get to that, I wanted to tell you the, the whole big plan. So you got data modeling then a little.
[00:02:43] Less concrete. A little more abstract is operation modeling. And then the last one is algebraic model. I've been considering doing a fourth level, which would [00:03:00] be meta linguistic modeling, which is where you make a new language on top of the existing language, kind of like a dsl, but I don't think I want to go there.
[00:03:14] I feel like that is a whole book by itself, and I'm just. I'm just not even gonna go there. I might mention it at the end. So data modeling is the skills that are required to represent the state of your domain in data to just a static view. Of the, of the state of your domain, like one snapshot of the state, the current state, what is it in?
[00:03:49] And that is deceptively simple. A lot of us, I think my listeners will be actually [00:04:00] pretty good at it. A lot of people aren't that good at it, and I want to talk about how you can take small components of the state and compose them up together. The main ways you compose things are by doing. There's two main ones.
[00:04:19] It's called product types and some types. So product types are like a two or a record where you're taking multiple. Values and putting them together, and they're called a product type because if you have, say, four possible values, four possible states in one of the pieces, and seven possible states in the other, you multiply the two numbers together, you get 28.
[00:04:51] So now there's 28 possible states because you have all the combinations of one from, you know, a and one [00:05:00] from. That's 28 possible states. Now, the, the other thing is called some types, which is basically where you have alternatives. So the four options might be a, some type of four different choices, right?
[00:05:17] Or it might be a sum type of two choices and two choices, or it might be some type of one choice and three choices. So you have all these options for composing your. State or the representation of your state using sub pieces, right? Smaller pieces of state.
[00:05:41] So there's product types and some types. Uh, if you need to do something more sophisticated, there's stuff like, uh, collections. So collections are usually the things we, we know. [00:06:00] Uh, and use already stuff like, uh, array or sets, things like that. These have the interesting property of being a kind of combination of a choice, Oh, I didn't say this.
[00:06:19] I should say it, that a, some type represents an alternative. So you can choose A or B, A. So let, let's say, um, if you're ordering pizza, you gotta choose a size, right? There's small, medium, or large. So the, the, you would represent, or you could represent that as a sum type of three tokens. One is small, one is medium, one is large.
[00:06:58] A [00:07:00] combination represents, sorry, a product type represents a combination. So in a pizza, you have both the size and let's say the sauce, and you have three kinds of sauce that you can choose from and three kinds of three sizes. Then that gives you nine possible combinations of those PE of different pizzas, right?
[00:07:24] So your pizza can be one of those nine. Okay.
[00:07:31] When you've got a collection, it's kind of a some type of products. Okay? So when you get into the toppings that you want on the pizza, let's say there are four possible to. Just to make it easy, but you can have zero or more toppings. And just to make it really simple, let's just say you have max three toppings.[00:08:00]
[00:08:00] That means you have a choice of zero toppings, one topping, two toppings, or three topics. Now that is like a first level choice. Now you have to choose the toppings that go into those slots, right? So if you have zero toppings, then you, you know what I'm gonna, I'm gonna talk about this more in another, uh, in another episode.
[00:08:32] Cause I don't want to go too deep into just like collections cuz it, it can, it's so much to. , but basically you got a choice of how many and then which ones, uh, but it, it does it all in one. And then different collections have different other kinds of features, like sets don't have duplicates and some collections maintain the order and some don't.
[00:08:56] And then things like that, which can align with the [00:09:00] way you want your model to work. And they all change the number of states, right? If you're using a set adding. Uh, anchovies or olives twice isn't gonna change the state, right? So it, it reduces the possible number of states that are available.
[00:09:23] Uh, I also want to get into, um, r uh, naming versus nesting. So if you're in a. A, a data model, and let's say you got pizza and you're talking about the toppings. Well, is the topping a nested structure with its own state to it, or is it just the name of a topping that is referred to? And I'm not going to talk about how you choose between them because both options, uh, are valid for different [00:10:00] situ.
[00:10:00] So I'll talk about that in another episode, cause I don't want to get into it too deep right now.
[00:10:11] Okay, so now let's talk about, uh, operation modeling. Uh, this is where, you know, you, you get good at data modeling. You, you kind of, you master it well enough and you start to realize that there's still so many choices that you have to make when you're building a data. and what informs those choices are your, basically your use cases and what kinds of operations you want people to be able to do on this state.
[00:10:41] And when you're doing an operation model, you're basically talking about what are the possible state change. And you do that, you analyze it in terms of possible state changes before you come up with the data [00:11:00] model, because the operations are actually gonna constrain what you, what kinds of representations you're gonna want, and that makes the problem up data modeling easier.
[00:11:12] So you do it first. So you just list out all your operations and start there. So that's operation. Is figuring out how to model state change. And usually you do it with functions. Uh, when you write your functions that are your operations, you're typically gonna be doing something that my friend calls signature driven development, which is you write the signature of the function and the signature is basically what are the argument.
[00:11:47] What is the return type and then what's the name? The name is important in the signature, and once you have that, once you figure that out, implementing it is [00:12:00] usually pretty straightforward. So the key then is to make sure that your signature makes sense for the operation that you want to be able to do.
[00:12:12] And one of the main kinds of operations you'll be doing is a. and in functional programming, what that means is you're gonna take the current state and some other arguments and return the new state so you have this mutation that is a function that doesn't change anything. I, I know I'm calling it a mutation, but I don't, and I'm, I'm willing, I'm perfectly open to new names.
[00:12:41] Uh, I know that that can be confusing, but it's gonna take the current state and returns the new state. And one of the important ideas in operation modeling is to, is to ensure that your functions are total, which means [00:13:00] that they are valid for any combination of valid arguments. . Okay. So any possible state, you can hand it any possible state, and it's not gonna like throw an exception because you, you did something weird, right?
[00:13:18] And then, so we're gonna spend quite a lot of time talking about how you can make, uh, how you can make your, your operations total, even when. There's obviously some state changes are not valid when the state is in a certain configuration, right? You can't always do this state change. Uh, but uh, how do you do that?
[00:13:45] Well, you have to augment, there's multiple ways. One, you can, uh, restrict the types of the arguments, right? So have fewer valid. You [00:14:00] can augment the return value. So one thing could be to capture the error as part of your data model, right? That your, your model always contains errors, right? It contains like the, the data model contains the error, right?
[00:14:16] It's part of the state. And finally, you could change the meaning of the mutation. . This is one of those more controversial things, but I think it's a, it's a valid thing if you've got a set of numbers. This is an example. If you've got a set of numbers and I tell you, remove the threes, okay? Or remove the three because there's only gonna be one possible three in there cuz it's a set.
[00:14:49] But remove three from the set. What if there is no three? You could just throw an error and say, No, this doesn't exist in the set. [00:15:00] It, how can I remove something that doesn't exist? Right. And that's, you know, that you, that's the arguable way of, of interpreting, uh, that, uh, that operation, the semantics of that operation.
[00:15:16] But another way to interpret it is to. . Well, if it doesn't exist in the set, I'm just gonna return the same set. Unchanged. Why? Why? What's the problem? So you're kind of reinterpreting it to say like this set without a three if it had one. Right. And it makes things sometimes go more smoothly, but it makes it total.
[00:15:42] There's no error there, right? If I say, Hey, remove all the oranges from this bag of apples. And you just hand me the bag of apples and you say, Look, there's no oranges in there. Then, you know, was there a problem? Does that need to be an error? [00:16:00] Right. No, it's fine. So, uh, that is, uh, one way of making things more total.
[00:16:09] Okay. Onto level three. and just to review level one, data modeling, level two, operations modeling, level three, algebraic modeling. This is where you realize that, hey, I'm never just doing one state change. I'm often doing a series of them, or they're happening even in parallel sometimes. I want to be able to model.
[00:16:36] That what happens if I do this and then that, like I wanna be able to talk about the properties of the system without, even, without, uh, talking about a specific state. I wanted to say at all times, this thing must be true. That's where you get into algebraic modeling. So there's some useful [00:17:00] concepts there that we can go into.
[00:17:04] So basically in the algebraic, just to to reiterate, you are, uh, modeling the composition of operations.
[00:17:18] So the first one I want to to talk about is the closure property. This is closure with an S closure property. It's a property from algebra. that says that the argument types are the same as the return type or argument type. If they're just one argument, and this is something that we see a lot in, in arithmetic and in algebraic expressions.
[00:17:50] So for instance, plus over the integers has the closure property. If I take two integers, those are the arguments I add them. [00:18:00] I'm gonna get another integer out. And why is this important? Well, it's super important because it lets you nest expressions. . It means that once I've got integer and I'm doing all these operations that have the closure property over integers, it means that I can build huge nested expressions.
[00:18:26] And I, I get to be very expressive with the way I, with the way I'm coding, not just coding like at the sort of to to. Remember we're talking about composition and nesting is a way of composing. Another way of composing is to just kind of do stuff at the end, right? So I say like, make a variable, a, do some operation on a value, assign it to a, and then now do some other [00:19:00] things.
[00:19:00] A, and assign it back to a and do some other thing on a, So I can do this kinda linear composition, just basically se sequence. or I could do a nested thing, which gives you another dimension of expression that, that you can do. And we do this all the time in, in, um, like arithmetic formulas. Another example is of the closure property in software is string operations.
[00:19:34] So string operations, you can, you know how if in Java or Java. Once you have a string, you can do like, turn it into lowercase now replace all the, the Ts with Ss, and now, uh, split it into four strings and then map over those and can cat 'em back together with, [00:20:00] with, uh, semicolons. In between them and that's a new string and you're doing this thing and it can just be one line and you never have to stop the line.
[00:20:10] You just keep chaining another method on it. That's because it's a string as the argument, and it's a string as a return value. So you're just always in the land of strings and it lets you build these neat, uh, expressions. Imagine if you had some strings, you know, had, were different and. Couldn't do the certain operations, you'd have to convert them.
[00:20:35] And now you've got, you know, you're, you're not in the same expression anymore. You're like constructing new things. And we wanna avoid that. And one way to do that is to like, stay in the land of one type and keep working on it. Okay. Associative proper. It's something you learn in high [00:21:00] school, in algebra class, but it's, it's actually quite a useful property and I've been thinking about how best to explain what makes it useful.
[00:21:10] Like what is the use of the associative property, and here's what it is. It allows you to break a problem up into sub problems and solve it with sub. It's solve a big problem by breaking it up and solving, making sub solutions, right? And then you can compose them back up together. That's all the associated property lets you do so as sticking with strings, you can break a string up into uh, characters.
[00:21:49] All right. Let's say into substrings of one length one. Now you can turn them all those individual strings into uppercase strings, and [00:22:00] then you can concatenate the strings back together. It's kind of a silly example, but it shows that you can solve the problem of upper casing a string by breaking it down into sub problems as long as you stay in the same.
[00:22:19] When you can caate them together. Conatation has the associative property. Once you can caate them together, boom, you're back in the, the, the original level of the problem, not the sub problems. Okay. Silly example. I'm, I have better examples in the book. Uh, commutative. All right. This one we talk about a lot.
[00:22:45] It basically means you can. Uh, you can do operations in any order. If I do F first and then G, it's the same as doing G first and then f And that also [00:23:00] has nice properties, or is, is a nice property. It has, it means that, for instance, if I'm building an editor for, uh, constructing a pizza order, Right? Cause I want to order pizza on the web or on an app.
[00:23:19] Does it really matter if I add, if I add olives first and then bell peppers or bell peppers and then olives in my order, right? It doesn't matter. It shouldn't matter. And so I need to ensure that that's true. And so I wanna write as part of the the algebraic model that. Is guaranteed. Okay. So that was a longer overview than I wanted to give, but I think, uh, it, this first, uh, pass at the, the, the table of contents, the, the levels.
[00:23:59] It [00:24:00] was good. So, uh, I'd love to hear your feedback on this. Uh, if there's anything missing, maybe I can find a place for. Uh, what you're most interested in, Anything that you think shouldn't be in there, please let me know. I want this book to be based on, uh, the feedback I get, especially on this podcast because these, you, you, you are, um, a good source of information about what people need to learn.
[00:24:36] And what's valuable, what has been valuable to you as a programmer when you're doing domain modeling? I'd love to incorporate that into the book. All right. Thank you very much. My name is Eric Normand. This has been another episode of my podcast. Thank you very much for listening, [00:25:00] and as always, rock.