All about the domain lens

In this episode, I introduce the domain lens, its questions, and its goal.


[00:00:00] All about the domain lens.

[00:00:04] Hello, my name is Eric Normand, and this is my podcast. Welcome.

[00:00:11] So I'm writing a book. It's all about executable specifications as an approach to domain modeling. And I've got a bunch of lenses, seven or eight, depending on the day.

[00:00:29] Now, these lenses aren't really a thing, right? I'm not saying that there are these lenses out in the world. They're just a way for me to organize these different perspectives on our software. Each lens is supposed to shine a light to help you focus on certain aspects of your software so that you can get more information out of the context, so you can learn more about the context and make better decisions. The lens will also tell you how to use that information to make better design decisions.

[00:01:16] Okay, so the first lens I'm talking about is I'm calling it domain.

[00:01:25] Another name I could have for it, like a secret name, top secret subtitle would be reality. I think one of the problems that I see a lot in software design is that, we don't look at the problem we're trying to solve. The main question here in the domain lens, also known as the reality lens, is what problem are you trying to solve?

[00:02:02] What I see a lot of people do is they have some kind of recipe for how to start building software for a problem. And this is a very common recipe. I see it quite a lot. But I'll also caricature it. I'm not saying the recipe is bad, so I'm not doing a straw man. I'm really just trying to give an example. Cause I'm not gonna try to destroy it or anything. I'm just gonna say, we're not gonna go there. We're not even gonna do a recipe. The idea of recipes in general is the problem.

[00:02:44] I use this one a lot, so it might be a repetition, but please forgive me for that. It's a really good example cuz I personally did experience this in school, in one of my classes. The professor said, here's the problem: We got a lot of students and a lot of courses in this university and we have to make it so that students can register for courses, and courses can register for students.

[00:03:21] The way we had been taught to do object oriented analysis and design was to look at all the nouns in the problem description, in the requirements, and those become classes and all of the verbs become methods on those classes.

[00:03:42] And so that means you need a student class and you need a course class. You're gonna have a relationship between the student and course. The student can be in multiple courses. You know, they're registered for zero or more courses. Well, that means you need a collection of courses, so you're gonna refer to many courses.

[00:04:08] And so when you register, it's gonna add it to that collection, right. But then at the same time, the course can have multiple students, so its arrow also, in the UML diagram version of it, it's gonna have a star on it, meaning zero or more students in the course. And so somehow you have to make it so that when the student registers in the course, it's kept in sync with the students in the course, and the course, in the students. And it's really hard. It's a really hard problem. It's like all these design traps, like mutual recursion between them and stuff like that. So the recipe was basically underline the nouns, underline the verbs.

[00:05:02] Nouns become classes and verbs become methods. It's not quite as simple as that because you can turn a verb into a noun et cetera. But you're basically trying to turn the ideas, the concepts in your text into classes and methods.

[00:05:21] Another version of this is is a hierarchies with classes and inheritance and extension of a class with a subclass. The silly example is you're given a bunch of animals, dog, and cat, and cow, and mouse, and you're like, look, these are all animals, so let's make a class called animal and make these things all subclasses.

[00:05:56] These are two recipes that we see a lot and people actually do them. So it's not like I'm railing against some oversimplified, contrived example in a course, in a university course. People actually do this.

[00:06:17] And what I want is to have a perspective where you don't need to follow a recipe. What is the problem that you are trying to solve by making a super class of a class called cat and dog and mouse and cow. What are you trying to do with that? There's no reason to do that. Likewise with the student and course scenario,

[00:06:54] What problem are you trying to solve? We're actually trying to represent a many to many relationship. That's the problem. It's a many to many relationship.

[00:07:06] Why don't we just write a class called Many to many? You can parameterize it on student ID and course id. It's much more directly solving the problem.

[00:07:19] But we don't do that analysis. I want this lens to at least help people start to think that way. So in these lenses, I'm gonna give a bunch of examples like this to try to get people to see from this different perspective,

[00:07:43] The main question is what problem is your software trying to solve? But one of the sub-questions is, how would you solve this with paper and pencil? So without a computer, what would you do? And if you were really building a university registration system, you would not make a piece of paper per student and a piece of paper per course, and write the course id on the student's paper, and then the student ID on the course paper. That's unlikely.

[00:08:23] What you would do is centralize the information. And maybe have a book, right? A registry, a register that has maybe one page per course, and you write student IDs there. Now you have this problem, which you've only represented one side of the relationship, so you need some other way to get.

[00:08:49] For a given student, what are all their courses? You can solve that also some way, but what you've basically done by asking this question is to really get people to drop their recipes.

[00:09:07] Your recipe of like drawing boxes with arrows is wrong. Your recipe usually is not the right answer. You really want to have a deeper look at the problem before you start coding.

[00:09:25] What I find so interesting about this student course problem is you don't even need a student class. You don't even need a course class. You just need a many to many relationship class, which is actually very generic, and then you need a student ID and you need a course id. You don't need a class to represent the person. The student Id identifies the person, and that's quite enough.

[00:09:57] Likewise with the animal problem. I know I didn't flesh it out very much because I think people jump there even without a problem to solve. They're like, oh, there's all these different kinds of animals. They let me make a type hierarchy, especially in the absence of a real problem. They want to create that.

[00:10:18] But imagine it was a veterinarian's office. The veterinarian can treat all sorts of different kind of animals.

[00:10:26] They have this paper. You come in with your animal. The animal is sick. You want some help. You gotta put your name on a list so that they can start, you know, treating you, they can put you in a waiting room, and then when it's your turn, they read the next person off the list. It's your turn. You can go. So you're gonna write your name, your address, and then you're gonna write the species, the kind of animal. It's relevant. You want to tell the vet the kind of animal they're about to treat, but it's not this privileged thing like the class that needs to be in some kind of hierarchy, right?

[00:11:15] You can just make it a text field if you want. You could make it an enum or something, but it could just be like the string "cat". That is a possible solution.

[00:11:28] So this is trying to open these questions. How would you do it on paper? It's trying to open the mind.

[00:11:37] Another question I've been putting down here is: Is the problem real or imagined? Is this a, is this a problem that actually needs solving? Does a type hierarchy actually have a problem with it? Let's say I am tired, I rely on my habits. I start making a type hierarchy and then I remember, oh, what is the problem I'm trying to solve?

[00:12:15] And so I come up with some rationalization for why I made a type hierarchy. Oh, maybe I will need to have some common methods in the animal, but I don't want to duplicate those in all the different animal classes. So that's why I need it. This is like a double check on that. Is this a real problem?

[00:12:44] Have you actually encountered some behavior that needs to be common among all these animals? But then some of it also needs to be different. Is this real or imagined? Let's a double check.

[00:13:03] And I've been thinking you could have this kind of quadrant where you have on one axis real and imagined, and on another axis anticipated and experienced. So it might be a real problem, but it's only anticipated. I haven't actually hit the problem yet. The most important ones are it's real and experienced.

[00:13:34] Yes, it is a real problem and I have witnessed the need for it. But then less than that is, it is a real problem, but I'm only anticipating it. Maybe you can wait. Maybe you don't need to build that into your model yet, because often our anticipation, our expectations, our predictions about the kinds of problems we're going to encounter, oftentimes they're wrong.

[00:14:06] Now of course the imagined ones like, why are you even there? You're just making it up.

[00:14:12] I wanna leave with a real example so we can actually apply this on multiple scales. Even at one line of code, you can ask, what is this line of code trying to do? What problem is it trying to solve? And I came up with this silly example, you know, I've been using Coffee Shop as a source of examples.

[00:14:36] You have this problem where you have three sizes, small, medium, large, and you have three coffee roasts. You have light, medium, dark. Notice medium is repeated between the two. And imagine we choose to use strings to represent these different values. The small is a string, medium is a string, large is a string.

[00:15:08] We might run into situations where we can't figure out if it's medium size or medium roast, so I might propose as part of identifying this problem that kind of brings up ideas. Well, the real problem is that they're the same. They should be distinguished some way, and I still want them to be human readable. So I'm gonna put size hyphen medium and roast hyphen medium. And then to be consistent, I'll have size hyphen small, size hyphen large, et cetera.

[00:15:50] So that's a very small problem. Very small scale. Now, look, I'm not saying that that's the right solution. I'm saying that that is a solution that this kind of question will expand that idea as a possibility.

[00:16:04] So on the other scale, there's entire software system. At this scale you might ask, well, like what is our software even doing? What's it for? What situation does this software exist in? Like what problem is it solving in that situation? And so if we're developing this POS software, one thing we can do is draw out an information flow diagram of the whole situation.

[00:16:34] So someone walks into the coffee shop, they tell their order to the cashier. The cashier punches it into the POS on the touchscreen. That's the software we're writing. Then that POS system, that software communicates that to the person making the coffee. And then the person making the coffee makes the coffee and hands it to the customer.

[00:17:07] One of the reasons I call this the reality lens is that that is the reality of our software. We're not trying to model how you make a coffee. We're not trying to model what happens when you roast coffee or we're not trying to model what happens when you mix soy milk with hazelnut syrup in a coffee if it tastes good?

[00:17:35] Like, we're not trying to do any of that. We're just trying to faithfully communicate the order from the cashier's head, through their finger into the touchscreen, to the person who's making the coffee. Just the order. This is key.

[00:17:55] I talked about this before as one of the key insights I had when I gave a presentation. I kept saying, the reality, the reality, it's all about going back to reality. And they thought, well, the reality means, the reality of coffees And I had to say, oh, I had to step back and apologize and say no. What I mean is the reality is that we're processing orders of coffee and you might, like, you have to know something about how this coffee will be made, what kinds of coffees are possible to make, so that you can record all that in the order, but the reality is we need to faithfully record the order and that's it. Record and communicate.

[00:18:50] That's the kind of analysis that I want to get people to be able to do, to like draw out an information flow, show how this software interacts with the real world. And that's just a light analysis to reset yourself. I don't need to make a coffee class.

[00:19:11] I keep dissing on OO analysis and design. That's what I was taught. So that's like deepest in my head. We don't need to model coffees, we don't need to have an entity class or an aggregate or anything like that. All like the real problem we're trying to solve is recording from the cashier, not from the customer, cuz the cashier is the one who's gonna type it in. So recording from the cashier to the person making the coffee.

[00:19:44] My name is Eric Normand. This has been another episode of my podcast. Thanks for listing and as always, rock on!