Domain Modeling for Humans and AI

Coding the Temperature Entity

Domain Modeling for Humans and AI

Lesson Description

The "Coding the Temperature Entity" Lesson is part of the full, Domain Modeling for Humans and AI course featured in this preview video. Here's what you'd learn in this lesson:

Mike implements a temperature value object using Zod schemas to align type checking and validation for Celsius and Fahrenheit. He also creates a monthly temperature range entity with an ID and links it to a location, emphasizing backend structure and API contracts.

Preview
Close

Transcript from the "Coding the Temperature Entity" Lesson

[00:00:00]
>> Mike North: Let's jump into our project and start implementing this. So where we're gonna start is in the Types folder, we're gonna go into. I'm going to close server for now. We're in packages types source. We've got a folder here called entities and we've got a folder here called value Objects.

[00:00:32]
So I think we have a temperature value-object to implement here, and let's start there. I'm going to create a new file. Let me close some of this stuff, which we'll pull up later. You can leave those tabs open because those are files we're going to need to touch temperature.

[00:00:48]
And I'm just going to follow the convention here because we're going to have another temperature ts that exists elsewhere. Temperature type ts and let's start with copying and pasting some code from an existing value object- [CROSSTALK]
>> Male Speaker 1: Should we switch branch, or what branch should we be on?

[00:01:11]
>> Mike North: You should be on the ddd-start branch, ddd-start.
>> Mike North: I'll make sure that we keep that where it is even as this project evolves. So we've got a temperature.type here. I'm going to start by grabbing this distance type because it's kind of got some interesting stuff in it and I just want to get a nice little starting point.

[00:01:37]
I'll just grab this because a lot of these will end up looking the same. So we're importing Zod, this library for defining schemas, and we're going to want a temperature unit schema. And let's just focus on Celsius and Fahrenheit, just C and F. And this is kind of our source of truth for what it means to be a temperature unit.

[00:02:13]
But this isn't a typescript type. Not going to risk spelling that. You can see temperature unit schema refers to a value, but I'm trying to use it as a type. So how do we get the type out of this Z infer? Just like this. So we've got a TemperatureUnit.

[00:02:50]
And look at this down here. This is what we want. So this lets you define a Zod schema and extract the TypeScript type that matches it. Why is this so important? This ensures that your compile time, type checking and your runtime validation of objects that sort of flow through the schema are very well aligned.

[00:03:07]
It's useful to have a source of truth where both things originate from the same structure. We'll export this as a symbol so other parts of our code base can use it. Yes. Question from online.
>> Male Speaker 1: Why are we adding validation logic inside the type.ts file?
>> Mike North: That's a good question.

[00:03:30]
Maybe I should have called this common or core. If you look at other modules in this file, this is a module that contains the structures of the data that we'll be working with. But this does not include just pure type information. There are some type guards here. This is checking to see if something is a valid distance unit.

[00:03:54]
And we may have similar things. So perhaps a poor name of the package on my part, but you can think of this as conceptually representing the shapes of the value objects, the shapes of the entities, the shapes of the request and response shapes, like the HTTP request response shape pairs.

[00:04:13]
But we have a schema here that's not just pure type information. And we may have type guards that make sense to put in the closest place we can put them with the objects that they relate to, the shapes they relate to. So we've exported the schema because that's going to be useful for whoever's using this to do runtime validations.

[00:04:40]
We'll export the type, but this is just the C and the F, right? It's just the unit. So we're going to need just to prove that this works. Now, temperature unit, like, the only error we're getting is this is an unused variable. So this is the type that we can kind of carry forward in our code.

[00:05:00]
We're going to do something very similar with the monthly temperature range, but we're going to create that as a different file here. So I'm just going to format this really quickly and hit save. And we're going to create an entity now, or the shape of the entity at least.

[00:05:19]
So I'm going to create a new file in this Entities folder. So you're in the Types package, source entities, new file, and monthly temperature range type ts. You can name it whatever you like, but name it like I did and your code will stay in sync. We'll need Zod just as before, and here we're defining our schema, and this is going to be an object type.

[00:05:58]
Like conceptually, what we want is something that kind of looks like this, something like that. So we're gonna look at this example and let's see how we can articulate that here. Question from the chat.
>> Male Speaker 1: Why does it make sense for a temperature range to have an id?

[00:06:29]
It seems more like an attribute of the actual entity.
>> Mike North: That's a good question. If we look back here, going back to this discussion, we could have said we have a temperature range that's a value object. And you can think of this as just the concept of Having a min and a max, and maybe we find multiple uses for temperature range in the future.

[00:06:51]
At this point, I think it's. It could go either way where we either say we're kind of embedding this concept of a temperature range with this concept of a month, a monthly piece of temperature data with a low and a high. We can always tease that out later if we need to.

[00:07:10]
But really this just comes down to whether you want to make the choice to tease that abstraction out right from the start, or whether you want to see it emerge as something like a temperature range. Emerge as something that's useful beyond this monthly temperature data, and we'll see how that goes.

[00:07:29]
Like, we still have a choice to evolve this in the future because ultimately we're going to have this API contract. We create like a request and response shape so we can internally start to model this as a temperature range and then have like a month that embeds a range.

[00:07:45]
Like, we could totally set up our data model that way, but preserve the existing API contract if we had to. As we're defining our schema, we're going to start with Z object and that all we're doing is this part here. This shape starts with being an object. We've got an id, which is a string.

[00:08:08]
We've got a month, which is a. We could do a number, but Zod also lets us do an integer. Remember, there's runtime validation that happens here. We can actually like as we check this data. This is a constraint that goes beyond just the number type that exists in JavaScript.

[00:08:30]
Then we've got the temperatures min and max. What we're going to do here is use the temperature schema, which I think we forgot to do a piece here, but we want the temperature schema now. We never finished our work on the previous file, so now's a good time to finish it.

[00:09:02]
This is what we want. So all we have is temperature unit here. Sorry to switch back and forth a little bit. We can finish and say the concept of a temperature is it starts with an object and it's got a value, which is a number, and it's got a unit, which is a temperature unit.

[00:09:30]
And you can point right to the schema that we just defined for sort of the C or the F. Then similarly, we can just copy the same thing that we used before, but instead of temperature unit, it's just temperature. So now we have the unit and then we're wrapping it in this object.

[00:09:54]
So it's the value and the unit and in both Cases, we export both the schema and the type. So when we go back to our monthly temperature record now, this will resolve and we'll use it for the min and the max with a comma and export it and then finally get the type.

[00:10:33]
There we go. If we look at this, there's our monthly temperature range. Let me get rid of the terminal so everyone can see. That's the structure that we came up with. We have an id, we have the number of the month, and then we have the min and the max.

[00:11:00]
Yes.
>> Male Speaker 2: Should we limit month to be 1 through 12?
>> Mike North: Good point. Yeah, does it make sense to have month be -16? Probably not. And Zod lets us do this. We can say min is. What should we use here, 1 through 12 or 0 through 11?
>> Male Speaker 3: Zero.

[00:11:23]
>> Male Speaker 4: Zero.
>> Mike North: Let's do 0 through 11. Why do we want to use 0 through 11?
>> Male Speaker 3: JavaScript, I think that's how it is.
>> Mike North: It's gonna line up really well with the date object, right? We can just grab, like get the month number and it should work.

[00:11:37]
So there you go. So now when we use this to validate data, we can ensure that it is an integer. Here's the min, here's the max. And you can even add things like a description. No, is it describe or description? Yes, there's the description. And this will like when there are error messages or if you use this to generate a JSON schema of some sort, these will be like what is applied on the tooltips as you're sort of hovering over a file that's conforming to the schema.

[00:12:16]
So we have our types, we have to handle this piece here. The way we'll do that is we'll say monthly temps, monthly temperature range schema. And we don't want just one, we want an array. If we were to do this, we'd get an error because that's just treating it like it's type information.

[00:12:44]
We want a Z array and that is the member type of the array. And so now if we were to look at what this location type ends up being like, you can see it sort of embeds all of this nice information here. So we've got the location, the monthly temps, the min and the max.

[00:13:11]
We're really articulating a reasonable structure here for how we think about these temperatures.
>> Male Speaker 2: Mike, wouldn't we want to put a location ID on that monthly temperature range schema?
>> Mike North: Yeah, that's a good question. We could do it both ways. In fact, tell me how you think about.

[00:13:33]
>> Male Speaker 2: Well, you're gonna store it in a table. And so each of those would have one location. And then when you get the locations, you resolve from the other table.
>> Mike North: Yep.
>> Male Speaker 2: You're not gonna store an array of IDs on the location table for monthly temperature ranges.

[00:13:48]
You're gonna resolve that from the database.
>> Mike North: That's a great point. So we could either say the location schema embeds the monthly temperatures, or we could say, well, wait a minute, those monthly temperatures, they're entities and we want sort of the belongs to relationship. We want the monthly temperature to belong to a location.

[00:14:15]
And we can totally do that. In fact, I think that's a better way to do that. Like just looking at the UI we're trying to provide here, ultimately we wanna get this working. We want to have a list of locations that pops up and we don't need to pass all those temperature ranges up to the ui.

[00:14:30]
So if this is part of like something that we seek to embed in an API contract of some sort, that's kind of unnecessary to include. So the other way to do this is to go back to monthly temperature range schema and say something like that. And now we can kind of like behind the scenes find those.

[00:14:57]
This never really ends up being exposed to our API. So this is more of sort of a backend concept. This would let us query by location and sort them by month. And then we have the points on our line. That's great.
>> Mike North: So there you go. So we've created a little bit of a soft edge on that relationship there, where we know that this has to be a valid location id.

[00:15:31]
>> Mike North: And then location type just ends up being this, right? Great for a dropdown.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now