Module 4: Implementing

33. Implementing Entities

Resources

Transcript

[00:03] Let’s talk about how we can represent the entities of our domain in the code base. So as we discussed earlier, the entities are the main building blocks of your domain. In the case of the Full Snack domain, some of our entities include restaurants, customers, shopping cards, menu items, and so on. And since these are core to the entire domain, they show up in the entire system, not just in your user interface, but also in your databases, database tables, for example. And in your API endpoints.

[00:36] So here we have an example of our core API. This is an endpoint from our core API, which is we used to use to get information about a particular restaurant. So this is a restaurant endpoint, it takes an ID and it gives us information about, about that restaurant. So this is very typical. It gets us a bunch of a bunch of data about the ID, about the restaurant, and we can use these endpoints We can call these endpoints from your application, using something like this is a very simple I have a very simple fetch function which simply calls that endpoint passing the ID and then it returns some JSON.

[01:13] I also have some additional fetch fetch functions here to get the restaurant menu and the restaurant categories. Now, it is very common and it’s very typical to simply use these fetch functions directly in your application, in your components. So I will say that for simple use cases, that’s totally fine. When your endpoint returns very small amounts of data or when the or when is just used in a single place. I think just calling the fetch method directly, it’s probably fine.

[01:45] But when it comes to your entities, I like to define layer of abstraction on top of it. So I’ll show you how that looks like in a minute. For now, let’s see, what is it problem with just using this fetch function directly in our components?

[01:58] So let’s say I want to use this function in my restaurant screen here. This is the main entry point of my restaurant screen. As you might remember, it looks something like this and it renders all of the information about about a particular restaurant. So I can call this function directly here. I can say restaurant is await fetch restaurant, and I can call this fetch restaurant function. And I’m just going to go hardcode an id of one here. But of course, this could be something that comes from the URL. And let’s just just print that data here on the body of the function of the of the application.

[02:42] So this is how the data looks like exactly as it comes from the API. There are a few problems with this. One is that the the attributes are nested here inside these attributes folder attributes object. There’s also this relationship objects here and these are conventions from my API spec, but they are not particularly useful for my front end. I don’t care about the difference between attributes and relationships. I just want to bring some data.

[03:04] It also comes with some data that we might not need. Maybe I don’t need for this particular page. There’s information about what it offers, if it offers delivery and pickup and so on. And also some data is incomplete. These categories list, for example, it does include the category name, which is the only thing I care about. I don’t care about the IDs. I only care about the name. So the data is not in the format that is useful for me as a front end developer when I want to render something on the screen here in the reviews, I also have some data that I don’t need, and this is also deeply nested in a way that I don’t need it to be in this shape.

[03:41] So there are some inefficiencies in this data structure that that we could that we could solve by implementing what I like to call a model. So let me show you how the model looks like. This is the layer of abstraction that we’re going to add on top of our API. So that or in between our API and the front end to make it, to make it easier and simpler to handle the data across our application.

[04:05] All right. So let me start by rolling all of this back. So I’ll go back to the original state and the place that I like to start when defining model is to define first a type. If I’m using typescript, I like to take advantage of that and define type for my entity. This case, we have the restaurant type, which is a simplified data structure for what I want the the restaurant entity to be represented in the front end. In the previous module, you might remember that we did this domain modeling exercise to define the shape of our entities so that that exercise can come. We can come very handy in this case.

[04:45] We also have our simplified data, our customer review object here for our reviews attribute, and this is essentially all the data that we need for this particular page, for example. Now how do we define a model? Then our model can take the form of our class typically, but I like to define it as a function instead. And the the model has to purposes. It has to return an object that complies with our data type. In this case, we want to return an object that has the shape, and it will aggregate data from all of the different data sources that are needed to construct this object.

[05:23] So we can start by defining a function that’s called getRestaurant, in this case that returns, in this cases is a promise, because it’s on a asynchronous function and it returns our promise of our restaurant object as it is the type that we defined earlier. And I will start by doing the same thing that I was doing before. I will call the fetch data or fetch restaurant function and I will grab the attributes and relationships relationships here. I will also call these other endpoints called fetch restaurant categories, and this is because I want to get the category names as well. This is where the aggregation of multiple endpoints is happening.

[06:02] Then finally, I will map through my list of reviews. This is to simplify the data structure so that I don’t have these deeply nested objects and also I don’t have any unnecessary data. And finally, I will return an object in a shape that compliant complies with my data type. As you might have noticed. Now, I don’t have an error here in my function, which means that this object is in the shape that I expected to be in the front end.

[06:28] And now we can use these function this get restaurant function, which is our model in the in any components or any functions that may need that data about the restaurant. So any time we need to grab the restaurant entity, we can call that function. So here, have an example in this in this restaurant. header component, which is the one, the one that we see here at the top where I can call, let me uncomment this and say I can say await getRestaurant and I get a hard code, the ID for now. But this of course will come from from the URL.

[07:07] So I’m going to save that and we’ll see. We’re passing the entire object. We we might not want to pass the entire thing, but here we’re passing the entire object to restaurant information, which takes an object of the restaurant entity type. And it will and it will print that data here. So that’s how it works. Of course, this in real application, we would like to style it much more nicely, but this is essentially a way in which we can pass the data from the API all the way to the components that need them in a way that it’s that the shape of the entity respects how we want it to look like in the front.

[07:42] So this is a much more simplified view of our entity compared to what we get from the backend. This may look like a small improvement, but remember that these entities are core to your entire application. So any inefficiencies that you may have, any nested attributes or incomplete data or unnecessary data that you may have in your object can really propagate to that through the entire copies so invested in creating model, even if it’s something simple like this function that we created here is typically a very good investment.