Should we have business logic in the UI?

Rate this content

How many times did you say or hear “this is business logic, it should not be here”?

In this workshop, we will create a modern frontend application using old patterns and you will learn how to build apps that have decoupled UI and services.

We will start with a React application that has its whole logic in the UI. Then step by step we will extract the rules and operations to hit that sweet spot of independence.

148 min
04 Jul, 2022


Sign in or register to post your comment.

AI Generated Video Summary

The Workshop focused on developing a quiz game about the TV show 'Friends' using React and the Meet dependency. It emphasized the importance of separating UI and business logic, and implementing a layered architecture. The workshop also covered topics such as event handling, tracking, and audio integration. The use of typed events and the challenges of implementing game features like a lobby and character animations were discussed. Overall, the workshop provided valuable insights into software development best practices and performance optimization.

1. Introduction to the Quiz Game Development

Short description:

My name is Samuel P. You can call me Sam. We will start by showing what we are building and then start some refactors. We will move things out of the component and use a React hook. After a small break, we will move to an application. We will have a refactor and make the application work triggered by something else. We will add more sounds to the test and create a lobby for the game. We will also create a Dan animation and a feature to change the name of the person's picture. Any questions so far?

So my name is Samuel. Samuel P. You can call me Sam if you wish. It's easier. I think it's a more universal name, Sam. I think I look more like this than this. Yeah, the tissues. So we have some contacts. If you want to reach me after the conference to clarify some questions, if you want to learn more about what I'm talking today. And what they're talking about today is all of this.

So I put 15 minutes in each step. But this will go more up to your speed. So some of them are way quicker than 15. Others are a bit longer than 15. But in average, they will be 15 minutes. So we will start to just show what are we building. Or in this case, rebuilding, because we already have something running. And we will make it in a different way. Let's use a different word for this. And I will share the code that we're starting with. And then we'll start some refactors on it. And we have a small break. We have two breaks. Three breaks, ten minutes each.

So in each step, it's okay if you miss some code. You can always check out branch and you'll be up to the speed of the group. It would be nice if you can do it by yourself. You some reason, you have to go to the door, you have something in the oven and you have to take it off, you can just check out the next step and you'll be all right. So after we see the state we have, we'll start to do some stuff. At the beginning, like everything it's like an UI application, and basically in the component, and we'll start to move things out of it. The first step is we'll a React hook, just like that, we are moving it out of the React hook, then we have a small break, and then actually we will move to an application. So this, I will show you a bit what is in this application I'm talking about because from step one to the step two, it's actually a lot of changes, so we'll have to see actual type and code. After that, we'll still have a refactor, and we have a few values in our application, and we will make it work, not being triggered by the UI but being triggered by something else. And then we will have some new features, so this application has one test and two features, feature flags working, and we will have more stuff on top. For example, the first feature we will implement is adding more sounds to the test, and then we will create a lobby for the application, because right now the application starts automatically. This is a game we're playing, we're making a game, a small quiz game, and the game starts automatically, so the user gets a bit confused. So what we will do is actually ask the user when you want to start, what you want to do, so we can play and start the game. And then we will have the Dan animation. We will understand who is Dan in a bit. Maybe of you, if you are fans of Mortal Kombat, you may know who is Dan. So we will create an animation similar to the Dan gentleman, and then just a small feature to change the name of the picture of the person that we're showing. You understand what I'm talking about, the bit. This was a feature required by my wife, because she was playing, she didn't like the names of the figures, and like maybe should the name that they use on the TV show. So let's see what they're going to do. Any questions so far? Good. All right.

2. Introduction to the Quiz Game

Short description:

We are building a quiz game about the friend's TV show. You don't need to know the TV show to play the game. There's a QR code for reference. If you don't know the TV show, no worries, you'll survive.

So we are building a quiz game about the friend's TV show. If you don't know them, it's okay. You don't need to know the TV show to actually play the game, but there's a QR code here and you can take a look at why those guys and why we're making a game out of them. I believe it's a very famous TV show. Does anyone here that doesn't know this TV show? Please raise your hand. No? Anyone that knows this, make sure that you'll listen. There's a feature on Zoom that actually raises the hand if you use it. You just pop the top so I can see if you have the camera off. Good. Thank you, José. Anyone that doesn't know? Okay. It's okay. You'll survive. No worries.

3. React Application with Meet Dependency

Short description:

We are building a React application using the Meet dependency. Meet is a library that helps us to implement the publish subscribe pattern, similar to how browsers work with events. It can be used anywhere, not just in the browser. We have an eBit test about Mortal Kombat, with features like a VIP feature and a unicorn feature. The game includes tracking, sounds, and special effects for correct and incorrect answers. We will be adding a signed feature to the game.

Okay. So we are doing this very beautiful application. So here we go. This is a React application. This basically was a bootstrap from a create React app. And the only thing that we had was the Meet dependency. Everything else is just JavaScript that we wrote, because Meet is JavaScript as well, but someone else did it.

Okay, I want to see hands again. Who knows the publish subscribe pattern? I should do the negative way. Okay. Who doesn't know? Who doesn't know as well? Who doesn't know publish subscribe pattern? We're good. All right. So okay, I can explain a bit what it is. So meet is a library that helps us to do publish subscribe pattern, so it can— it's basically what browser is doing, no? You have an element, and you can do— on click, you do something. So you're subscribing to an event, and this guy will actually emit an event, like, okay, someone click me. And you can have multiple people there, you know, like on click, on click, on click, on click, and when actually someone click this element, it'll emit an event to you like, okay, I've been clicked to something. So this is something that works not in the browser, so it can use it anywhere. So this is one of the advantages, because if you wanna use this node server, it will still work and the other custom events will not work here. So it can actually go without it. If you wanna just use the browser, you can use the custom event and keep going. But I'm going into many details that I didn't plan to talk about. So let's go.

So there is an eBit test here and eBit test is about Mortal Kombat. We will show it in a bit. That's why you have done on the mixture and you have two features. So by default, the time is eight seconds. They have to take eight seconds to reply. Who said this thing? How are you doing? So if you know the TV series, probably know who said it. It is going to take ten seconds, I guess, something like that. And this is called a VIP feature. And you have a unicorn feature. So the unicorn feature actually will tell you who said it. So basically we are cheating. So it's just for the fun. So this will have tracking in place and sounds many, many, many sounds. So talking about sounds, let me share my sound with you because we will need to hear stuff. All right. Maybe not burn the ears. And let's go. So demo, demo, demo, demo. So let's see what we have. So this is our game and this is the starting point. So is there any left to hand up? Some purpose? No. Cool. So this is the game. So as I said, if you open the website, the game will start automatically. What is kind of annoying. Sorry, I have the unicorn on. So if you click. Oh yeah. Phoebe, she said, oh yes, it was me. Could you hear it? Good, but if you fail. You say, no, it was not her. And so each person will talk. If it was, if it wasn't. No. No, I'm sorry. You are totally making this up. So, and if you fail three questions in a row, there's an anti-combo. So basically we have a special sound for it. And if you get three in a row, we have a combo sound. So like Joey. Monica and Joey. So we have a special sound when you do a combo. So we are starting from here. And we'll add this feature that is signed. I'll just jump to the code and go to master. And if you come back here. So the game doesn't start by itself. That's, what's good.

4. Game Features and Repository

Short description:

We have a lobby and the Mortal Kombat version. We can set cookies and use a timeout. We can change the combo for the control version. There's a different tea song and famous animation combos from Mortal Kombat. We will be working on this. Any questions? Let's check the chat. You can clone the repository and start from step 0. Be careful with the naming convention. The generality will be the same in all the steps.

So we have time to, I don't know, do whatever we need to do. And we have like a lobby out. This isn't an extra feature. You can have some music in the background, just because we can't and we can start playing. So the same situation. So now if you want to try the Mortal Kombat version, I just need to set cookies so that my tests are seen by the cookies. Oh, another feature I forgot to mention, the timeout. So if you don't reply, they will call it. So I will just change to the Mortal Kombat so we can see the difference. But before that, I will show you the combo for the control version and then we'll jump. Okay, so let's do it again. Start! So because I'm cheating, I don't seem to have been by heart. So Rachel, Monica, and Joseph. Oh, my God. So we have Janice just showing the combo. And this is the kind of done animation that we'll have to implement very soon. So I will change it so we can see actually what is the Mortal Kombat version of it. So now, if you play, actually you have a different tea song. All right. And if you start. Round one. This is familiar for some of you, I would say. So Phoebe. Well done. Rachel. Well done. Joey. Frosty. And there are the famous animation combos from Mortal Kombat. So this is what we'll be doing or working on. What are you waiting for? Yes, yes. And I'm sorry. Any questions so far? Good, good, good. Let me just check the chat. Hi. The cloning, I will show in a bit. So we didn't miss. So the people are still joining. You're not missing much. You're just showing what I was doing in the agenda. All right. So let's, what we have after the demo. All right, so here we go. So you just clone stuff. This is the repository and it can clone it. If you don't have any client, well, you'll need some. Just let me know if you don't have any kit. So you need to wait or not for you. Is everyone alright with kit? Sorry, could you paste the repo address in the chat? Yes, yes, yes, yes, yes. Sorry, it's sharing one of my five screens. I just sent it. No problem. Oh, thank you. Thanks! So actually I can share the next step because... So, so we have a few steps. Step 0 is actually the one that has nothing on it, so that's where we should start. The master is the last version. So don't use the master. Otherwise you don't have anything to do. Everything's done. And then we'll jump from step to step to step. Be careful when jumping from step 1 because in step 0 we have step-0. But all the other ones have step underscore 0. Just a trick. It's not a mistake of my part, is it? So if you go to the repl, you'll see that we have all the steps here. So let's go to the 0, and we have some instructions that we will do, and basically we do nothing here. We'll just see the code and keep up with our lives. The generality will be the same in all the steps. So it's just telling you what you are trying to do. All right.

5. File Structure, Infrastructure, Services, and UI

Short description:

Jump to step one for instructions and a proposed solution. Overview of the file structure: public folder for assets, domain folder for entities, infrastructure for data retrieval with repositories and mappers. Services for AB testing, event bus, and feature panel. Tracking and data test functionality. UI folders for hooks and components.

If you jump, for example, just a spoiler. If you jump to the step one, you'll see that you have some instructions to do what you have to do. And if somehow you struggle to do it, we have a link for the... like a proposed solution for the change. So you can always consult... the small link there. So where are we? Do we have the repo connected to the sheet? Is your internet too slow to do the endgame install? It's normal.

All right, so one of the things I probably never count as doing things I will kind of show what we have, what is the structure of our files so we can navigate a bit easier. So overview. So we have a public folder is what our assets are like images and sounds and some fake APIs because we didn't implement any API but we have some fake calls there. Actually, we are using a real open API in the B2oc. So we have our domain this is where we have all our domain entities. At the beginning, they are basically some, some structures, they don't have any logic. They don't know what to do. Anything, they're just like a character has a name. It has a photo and it has object reflections. What she can say? She can say yes, she can say no. She can say other thing. So and if she has different positions she has different ways of saying something. But they don't know what to do anything. It's just the data, raw data.

So infrastructure in the beginning, this is one of the followers that we will play a lot. But at the beginning, it is just the way we reach data. We don't have much more. So we have two repositories. One to get the characters and one to get the quotes. We have the mappers. Because we will fetch this data from some place if we're coming to data transfer object, but we don't want to work with data transfer objects. We want to work with our domain entities. So we have a mapper that will take this GTA object and map it to something that our application knows, not something that was optimized for a network transaction. So in the step one, this is everything that the infrastructure should do. It could do any more like caching or other stuff, but we are not there yet.

So services. So I've provided some very basic services to do AB testing. So if you want to consult an AB test or does the impression or heat of the test. The event bus is the neat wrapper that we will use a lot. At the beginning, you're not using it yet, but it's there already. And the feature panel, so is the same tool, consult the feature. So if you have a feature enable, so if you can react and work with it. So I have a locker in the tracking. So the tracking actually do the tracking. We can see here. If I go to my browser and if I go to probably network. There you go. If we just do this thing, just filter for tracking. If I click on something, I'll see the tracking is actually happening. So we are sending some values. Okay, it was yeah. Some stuff happened. And the same for data test. If I refresh tracking, tracking. Probably it should be working. But it's not. Yeah. All right. But you'll see things are working or not. Let's see what we're doing for. Let me just make sure. All right. So this is an UI. Okay, UI. We have three folders. So we have a folder with hoops. That are React hooks. There's not much to add here. Components. They're basically just dump components. Our components do nothing. Only this one does. And we will try to solve this.

6. Container, Adapter, and Reduce Folder

Short description:

The container does everything, including tracking and fetching. We use the useReduce hook and have an adapter as the reducer. There's also a Reduce folder for miscellaneous code, like utilities for cookies, object conversion, sound, and array shuffling.

So the container does a lot of things. Actually, it does everything. I mean, everything is everything. Tracking. Fetching. Everything. Sorry. And we have a folder called adapter. So we are using useReduce. All right. Who knows the useReduce hook? All right. We are using that. All right. Okay. So this adapter is the reducer. We have the state. And there's some helper here to calculate the points. And the actions that we can send. All right. Yeah. And then that's it. And then actually, we have a Reduce folder, like any other project is where we put everything that we don't know where to put. Not even in the slide. So I just jumped from random corner, because I have an idea where to put this kind of code. And there's like some utilities to get like cookies and convert objects to string, and play the sound, and shuffle, arrays. Very random stuff. Cool.

7. Moving Code to Step Two

Short description:

In this workshop, we will reverse the tendency of having a fat UI and a slim domain. Let's move to step one and see how the application breaks. You can use VS Code to view the README files and follow the instructions to move the code. If you finish, you can move to step two. However, all the code is still in the UI, so this step didn't help us separate the logic. We will create a new folder in step two and make further changes.

Are you ready with the cloning? Good. So here on our left, this is a very blurry gif. I hope you can read stuff. But in our left we have our UI, so our container. And then our right, we have our domain. At least the HootSegregate of our domain. And we start with a very fat UI, as you can see. And a very slim domain. So and what we will do in this workshop is actually revert this tendency. So you see that actually in the end our HootSegregate is quite smart and our UI is quite done. Yeah, so let's, let's get on the ride and continue.

All right, let's get to know if everyone is actually ready to start doing coding. Anyone is someone at this still on in the repository or everyone is on? Raise your hand if you're still fetching stuff from the internet. All right, good. Okay, so as we saw, so now we have to go to the step one and the application will stop working. So we're able to actually start application is everything working. You should go to the steps.

Okay, so this reality will change if you check out the step one, the application we've broken. And so if I can... here, if I do the same key checkout, step underscore one. Interesting platform, okay. So it's quite hard to read a README file like this. But if you click on this nice button and I don't know if you use Visuals, use VSCode. Well, I don't know. I use VS Code. So for the ones that use VS Code, if you click on this button on the corner here, you have a nice version to see the README's files. So we have a link for the files here. So open this file and then take the code from this file to this one. So we will... We will have, like, 15 minutes to do this task. I'll be around here. If you have any questions, just let me know. So as you see, like, we have the skeleton for the book and we have the code here that is not being used anymore, but is still here. So we just need to move it there. Not only but you have to say, like, just the imports and some other stuff. Take this code. Come here. Paste. Things complaining. Great. Done. Still complaining. Paste. Still complaining. Import. This is some trick to import everything. Okay so, So, Okay, So, So, OK. So, So, um so what's it doing with everybody any step that is being complicated to someone in the break rooms So, if you finish, you can just check out the step too, there's no need to comment You can compare it with the proposed solution but I don't think it can do very much You can try to make it sense here but it's no point because one of the steps will be to kill all this code anyway. You have 60 seconds, it's no problem if you don't finish, you can check out the step too and it will be done. So, let's move to the game and see what happens. Why are we doing it? If we take a look and come back to our code, all our code is still in the UI. So, it is nothing. It's still here. So, like, if I go to my domain, it's entities, characters, and this one. It's still, it does nothing. So, it's still, like, my UI is still doing everything. So, actually, this step didn't help me much to get the logic out of my UI. It's still there. So, it's just a disguise in a book. That's good, I guess. So, now, we will create a new folder here. When you go to check out the step 2, it will be there. And let's see why. So, if you actually check out the step 2 at the moment, you probably will get a bit confused because it's a lot of changes. And I would like to give you some context before you actually start working on it. You can, because there's some instructions. Let me see what I say. That will be interesting. Step 2. So, I'll go to this file, removed all code, emit, and event.

8. Onion Architecture and Layered Design

Short description:

We changed from step 1 to step 2 by giving semantic value to the folder structure. The application folder, closer to the domain, is where the action happens. The onion architecture has layers, with the domain being the most important. The UI is outside and changes frequently. The UI is a mechanism for content delivery, not the application itself. The domain should be independent of libraries and can work in different areas. The application knows what it needs, but not the implementation details. The same endpoint can change multiple times during refactoring.

Okay. This is a bit strange. All right. Let's see what I'm trying to tell you here. So, up to the point... Okay. The general idea. I forgot about this part.

So, what we changed from the step 1 to the step 2 is actually give some semantic value to this folder. So, as we said in the beginning, we have a domain folder, every infrastructure, and every UI, but the code was just there. And it can do whatever you want. So, it's like everything in the root, you shouldn't actually follow a pattern architecture something that make this folder status meaning. And the step 2, we will actually have the application folder. That is the part of the application that's here closer to the domain, that will make things to happen. So, this is actually the layer that will do the action... The application. There's more things. Let's step by step. Let's see some high concepts of this idea of making this an onion architecture.

By the way, is there anyone that's familiar with an onion architecture? So, this is like an onion. You have layers. You have one layer to access the next one. A layer to access the next one. The most important part of our application is the domain. All our rules, our core business rules. And, ideally, it's the part of the code that changes the less. So, you don't need to change it a lot. But, the UI, on the other hand, it is outside. It changes a lot. The button is green, tomorrow it's blue. Or it's the less and then it goes to the right. It's always changing. Let's keep going, because this is not the point of the workshop. But please ask me things if you have some questions.

So, one of the main points is, what is the test? The dependencies work from the outlayer from the uni. So, for example, the UI can access the infrastructure, can access the application, can access the domain. But the domain can't access the application. The domain can't access the infrastructure. The domain can't access the UI. The UI is as pure as possible, as it can get. I think of a point for that. Because if you make our UI just pure JavaScript, you are agnostic of the framework. So, it can actually change direction at any moment. React is very popular, and it will be for 20 years, I hope. But it can come like something else that will kill all your application, like 10 years ago, FakeQuery was a thing. Exactly. So, UI is just a mechanism to deliver your content. It's not the application. It's just the way that you get your application to a user. If you put everything in the mechanism of delivery, you'll pay a lot for this delivery. So, as I said before, the domain should be independent of libraries. So, if you have something that your domain needs, please inject it, inject it, so it can actually shape it as you need, because the same domain can work in different areas. Imagine, for example, in our case, we have an application that has different white labels. So, the same application works in different countries. It has different rules, different UI systems, whatever. We have the same domain, but there are some specific things that are specific for specific areas. So, everything should come from the top and be injected. So, make it as clear as possible. And application, the same. So, the application knows all those stuff, but doesn't know the details. For example, repository. So, you know that your application needs to get this data from somewhere. The application doesn't need to know the details, like what is in the service. This is using GraphQL. This is REST, this is JSON. The application just needs to know I need to get this data. How it comes, someone will tell me. And this can change any moment. For example, we've been from a refactoring recently. And the same end point changed five times in one month because it was like we're changing a lot of stuff.

9. Organizing Code and Testing

Short description:

Organize your code around business ideas, not frameworks. Write your business rules as your product owner tells you. Be agnostic of what you are using and build the business agnostic of whatever you are using. The UI layer should be completely independent of the other layer. Make everything easy to test by injecting dependencies and avoiding rendering in unit tests.

So, it was an endpoint, and then go to API gateway, and then we changed to GraphQL, and then we changed directly to the Play. So, we were all changing the way that the data was reaching the application. So, if you put this in the application directly, you're copying the stuff. So, just give application or to actually get your data or anything else, cookie or whatever.

Okay. So, and again, organize your code around the business ideas, not frameworks. This is funny. Yeah. So, you should write... We should write our business rules as your product owner tells you. So, the user goes to the website, it does this, it does that, and it should describe your application like in a product owner perspective, because if you write the code like, I have this database, React does that, and then I have a router, it will be hard to assert that you are doing the correct thing because you are plugging tools to do your job. It's probably easier to describe what the code is doing exactly like someone asked, because the product owner probably doesn't have an idea what is React or GraphQL or this kind of stuff.

And this is something we already talked about, so the dependence rule keeps the tails away from the core, so you know that you need to reach data, but you don't need to know how to get the data. Yes, I just wanted to ask if you have an example, scenario for the second last point you mentioned, organize your code around business rules, not frameworks. So if you just take for example, this quiz app that you made, how would that apply to this quiz app? Yeah, I'm not sure if we have in here a specific example for that, but recently we had, for example, I can give an example from our daily routines. And we have a problem that we are trying to solve an issue. Maybe Ruben can help me to remember. So we were trying to do something. Give me a second. And, yeah, because we're expecting that the UI has to do something. So we're changing everything from plain form to a stepper. And we're trying to organize our rules according to the stepper because first we will show this step and this step has this fields. So at some point our domain needed to know that we are in the stepper. But, no, it didn't. So the way you shape your events, then it will actually, so you'll shape application the way your events go. So the user, so you have an input and then the domain execute an action and so on. So you start following this actions, actions, actions, actions. Because if we try to start, if we start to mold our domain the way it looks, then it's time to try to change the way it looks, it will be hard to change it back. So, the rules will be the same, because we are making the form, we have a validation for a field that is the same, doesn't matter if this field is shown in a step or another step or it doesn't matter. I'm not sure if I can explain somehow this question or I went around it. So, mostly have something that even do in architecture... Yes. Yes. So, if you define the events, anyone else can actually react to them. If you define your UI and your tools, you are stuck. So, that's what we're trying to solve. If we define the way our core works regardless... Regardless? Regardless, one of those words. Choose the correct one. You can shape the UI or any other services around them. So, this is the idea. So, be agnostic of what are you using and build the business agnostic of whatever are you using. So, it can build... It can use this core in other places. We have this long complex validation form in the client, and it can just take this bit and share it in the GraphQL, and it can evaluate the same input. It doesn't know that it even has any UI. So, it just needs to know that there is something going in, in those stuff and it comes out. So, it can share like all these core in the client, and in the GraphQL for example, or many other usages. So, that's the idea. I would say that if you have a UI layer, it should be completely independent of the other layer. And the X state, is it the UI concern is? Probably because I'm not very familiar with X state, but I think it's some kind of Redux thing, the state machine. Your core, your domain, basically is your state, in this case. So, what we will do here, we will grab our domain, and the UI will adapt it to a state. So, everything that your UI will know is the domain. So, it got, okay, my domain has this state right now. And then, the Reduxer will take, according to the event that we're treating, like something was loaded, something failed, notification from hell, who knows. The reducer of your X state or whatever state management you use, will take this new blob of information and it will adapt the state. That's why I call, actually, an adapter inside of the UI. Because all your input is the domain state. So, basically, already as some how a state management, because this can work independently of the UI, it can just make here a jQuery, re-reacting back to jQuery as it's vanilla JavaScript, can do the same stuff. So, you have something that has to take your domain, and according to an event that occur, it has to shape the state in case of having some kind of reactive framework, or just update your DOM directly. It's up to your strategy on an UI. So, we're using React, but you can use whatever or even nothing. And make everything easy to test. We have zero tests in this framework, but the fact that, actually, we can inject everything, you don't need to be mocking everything. So, you can just pass mock or pass whatever, so you don't need to, for example, if you wanna test if something was fetched, you don't need to render something, you just test it directly, because it can access each of the layers and test it, you need to test it. Because something that's very common is that we do integration testing to the unit testing. So, we render a full application to test if something is actually working, or a render-use component to test if something was done. So, here we are kind of avoiding all this overhead of rendering stuff in the unit test. I think that is a really good question.

10. Domain Rules and Separation of Responsibilities

Short description:

The domain has the rules that shape the use cases. The UI component is the entry point for user interactions. We want to move away from having the component do everything. Instead of going to the reducer, we can bubble the user's intent and broadcast it. The application handles the intent based on the domain rules. The domain itself is a set of rules for what, how, and when to do things. The application or other services execute actions and update the state. This approach separates the responsibilities of the UI and the application.

So, he's asking if is domain a place for the use cases? Yes, I will show it in a bit. Not really, not the use cases, the use cases is that application, the domain has the rules that allow the use cases or not, or shape the use cases. So, each cases we'll access the domain and do something it depends on your domain rules, but the application is the one that has the use cases. So, yeah, we all check here in a bit.

Let me see, there's something else here for which I haven't followed. So, if you can help me. So, everything the rest is fine. So, I have a drawing, I think is one of the next that show this use cases situation. Let's see if it's this one. Yeah, it is good. So this is our UI, beautiful. In our case, we use React, but as I said before you can use whatever you want, literally we made the console simulation thing. So we have everything the same, the user using a terminal to build the code and it was working. So we just changed the way that we ask things to the user and application was working. So we have many users. So I put many users because the application can work differently according to the user. So the user actually uses the screen that React component to interact with our application is our entry to the application. So it clicks, it scrolls, it views, it loads, what was it called? The mounts, yeah, the mounts and the component, whatever you want to use to trigger an interaction from the user side.

So now, we're first in our step zero and step one, our React component is doing tracking, is checking AV tests, is section data, is mapping data. It's doing everything. So a component does everything, creates an action, sends this action, that will text from the reducer, the reducer takes this action, maps it to the state, and then React is listening to the state and does this magic. This is what we have in a step zero and one. But we want to move everything away. So we already took all these actions from the screen and it worked into look, just to make it a bit clear the change. But what if here we do a detour? So instead of going to the reducer, we send this action, not this action, so let me correct. If we redirect the intent of the user, not even intent of the user, if we just bubble what happened in the browser and bubble it somewhere else, like someone clicked a button. That's all that the screen has to do. That's basically what a UI DOM does. One click, you just bubble. Okay, someone clicked on this. So instead of actually doing the job, I just say, okay, someone clicked on me and just send this to everyone. Thanks for that. You broadcast this UI intent. Okay? And this goes to the event, that's why I said broadcast. So for the ones that don't know what the publish subscriber, so the screen here is emitting an event. Like UI, click UI, start getting clicked. Okay? Something like this. And then the event must get this thing and it will notify all the subscribers. And one of the subscribers for this can be the application. Or not. There is things that the UI does that the application doesn't even care. For example, tracking. The user sees the screen. Application maybe doesn't need to do anything but the guys from the analytics, they need to know that you saw a screen. So, you'll see what I mean. So, the user clicked there and then it just literally says, I click here and send it to everyone that is listening. And you have an application with a news case like Dave was asking. So, okay, yeah, I saw you click here. I know how to handle these things so I will do it, you know? And it may need some... Let me just move this and stuff around, please. Sorry. So, you may need to consult the domain because there's some rules or some interfaces or something that they need to actually consult. But the domain doesn't do anything. This many ways of seeing DDD and many authors write it in a different place but what they're doing here is, like our domain doesn't do anything, okay? It's one of the approaches. All of this stuff is application. The domain is just the set of rules. Like what to do, how to do, when to do it, can I do it, like rules. Let's say then, those rules can differ from users, can differ from infrastructure, can differ from many things. It can have policies. So, you have a policy for a specific user, you have a policy for a specific something, okay? Depends what are we building. And okay, so you execute this action and then, and then, and then, okay? The application said something was done. So actually, the application is the one that does things. Application or other services. Then, I said done because the past tense here is very important. Something was done, okay? It's not like a query, literally, something was done, right? And it goes back here and, okay, so something was done and then it goes to the reducer and the reducer does this stuff. So basically, we're just tutoring. So before, the screen does everything and then reduce the time, all right? Now, the screen just manifests intent of doing something. Someone does it, and then it goes back to the same place. And with this strategy, we could just remove event plus and use the application directly since you're will. But we are using an event plus here because we can delegate things to other places like analytics.

11. Delegating Tracking and Isolating Features

Short description:

I want my application to delegate tracking to specific people. Features can be loaded independently and are independent of the application. Audio will be moved to a specific service. It can be easily turned off in one place. Remove unnecessary code.

I don't want my application to be doing tracking. I want someone specific that knows how to do tracking. So my application does how many cases it has to do, and it can delegate all of this stuff to other people. So I can easily set up a tracking without interacting with my UI or changing my UI or changing my application or changing my login or changing, whatever. I can start building, I will burn myself, microservices inside of my application, in my thingy.

So in the same, like feature, like a feature can be loaded independently and be completely independent of application. I can just put it there. Like, is my feature enabled? Yes, okay, so I will subscribe to those events and do stuff. If the application, if the feature is not even enabled, okay, I'll do nothing, okay, go away. So the same with, in our case, the audio. We will move all the audio to a service in specific. Each time something happens, now you will play it. So we can potentially touch the audio, we can even put under the feature flag. So I don't want the audio to be bothering the users anymore, turn it off. And it can turn off the audio very easily in one place. Remove the code. Remove the code is a step, remove the code. This is all like, is isolated, isolated. I promise I can talk better. Okay, isolated. And the same for whatever you want to do. Okay.

12. Performance and Connecting Actions

Short description:

In terms of performance, using an Event Bus in a client application should not be an issue as long as there are not thousands of events running simultaneously. Grouping changes and sending them in the same event can optimize rendering. Multiple React apps can be used on the same page by setting them up as portals. Let's move to step two, where we will connect the 'start new game' action in the same way as the character click action.

Questions. I'll say that this will be a bit confusing. Let me see the chat. Okay, Ruben is out for a bit, but we will return. There's some particular bit that is very confusing. Because this is what we will be doing in the next steps. Actually we will refactor some stuff to actually go through this flow and we will add new features to go through this flow. Ivan? Yes, thank you. In terms of performance, will this new Shannon work faster? This is, I will say, regarding the performance application, what's the performance. Yes, is always a very good topic to be concerned about, but this is what the browser is doing anyway. So, you are doing... This is gonna be a performance issue if you use Event Bus on large scale backend services where they have thousands of events coming through, but in your client application, you will not have thousands of events running, I hope. This is like someone clicked and you have four subscribers, five subscribers, 20 subscribers, even if it's a hundred subscribers, it shouldn't be an issue. It could be an issue here in your reducer, of course, because if each of them is triggering new changes that you are listened to it, it's the same or even worse with the hooks because, you know, you are... You know how hooks work. I didn't find any issues with performance. Actually, I found many benefits because when we were working directly in the screens, we were waiting for hooks to do stuff and memo stuff in references and use states. And it was very hard to know when I have to do something. And here because any of the components have access to the domain, you can just emit a combo, combination of events, if you want. Sometimes we did like, we have a situation that if the user change one, something on the form, 20 other things changed. Okay. And there can be a sync. So we can actually group all this change and send it in the same event. So actually, instead of 20 renders or more, you have one. So in terms of rendering, it can actually optimize this stuff. But if your concern is about like the pop subscribing situation. I don't think there's an issue because this strategy is using a many frameworks under the hood that we don't know. What was it? I think, but the next chance is using this situation. They are using this under the hood to communicate. Thank you. It sounds great. And in this way, it looks like we can use not only one application. Yeah. I can use like several React apps on the same page. Yes, yes. For example, something I didn't do, but for example, there is one of the features that is a Dyn animation. We are using the same React application to this animation, but in reality, you can add a new why application here and you set it up and just run like a true portal or whatever you want. So I can start to build this stuff like this. Okay. Thank you. All right. So after all this thing is going from one place to another and blah, blah, blah. Let's try to do an example. So let's go to the step two. And there is a read me here. I will show you the read me. Step two. Oh, well I should show you the code. Let me show the code. Step two. So, oh yes, okay go away. I don't want my changes to disappear. Okay, step two. And if you take a look now, our user actions is way smaller. Right. Our UI is still the same because we are already using the hook. But I changed it a bit, I can show you in a bit. So, here as we said, when the user clicks on the character, it doesn't do anything, it just says, okay, the character click. And you meet this event. Okay? We meet it and someone will take care of it. And our task here is to do the same with this one. When the user clicks start game. That will do the same thing, it's not done yet. So this is our task. Something that we did is we broke the audio. So we will not have audio until the next step. So we will need to fix the audio in the next step. But let's not concern right now on the audio. So our step is to actually connect the start new game in the same way. So, we basically will say, someone clicked here.

13. Infrastructure and Domain Rules

Short description:

We have a set of infrastructure that includes a bus for events, a logger, and a hoot aggregator. The hoot aggregator handles calculations for points based on time and combos. We also have functions for set timeout, updating codes, starting timeouts, setting run values, and starting a new game.

We can even see it look, here we say, UI, character click, and here, application, new codes loaded. So, the code was done. It's already ready, to do something. Okay, it's a difference. So, this is in the wrong place, this is not application. This is a UI. So, things to know here. Important things. So this, with direct flow that we took, is to be set up. All right. So our user application, basically, has our use infra. I will show you what is use infra. I said that the infra will be very used, and it's starting to use it. The use infra basically, the main purpose is to make a single turn of your infrastructure, because it will be the same infrastructure for all applications. So, you put it in a reference, and you only create it once. Okay, what is the set of infrastructure? So, we create a bus. This is the meet thing that we're saying, like, saying. So, bus is, show me type. TypeScript. Okay, with a bus, it can meet an event. You can subscribe to an event. It can turn off an event. That's it. There's something new in version three, but I'm not sure, but basically that's it. So, I have a logger. We have our hoot aggregator. Our hoot aggregator actually has more stuff now. So, we can actually do things in our hoot. For example, the calculation of points. It's a domain rule because the points, and it's like, okay, depends on the time that you took. And if it is a combo or not, because it has a multiplier. So, this is a specific domain rule. So, we move it here, down to the domain. Where it belongs, not there why. More things that we move here, like set timeout. Yes. Update the codes. Start timeout. Set run value, so, when the user actually tries to vote on a character. Start a new game. So, what we have to do when we start a new game, we have to refresh our codes, we have to update, that's the setup. Okay. When you start a new game, you are in the first question. So, you have to set this stuff up. And that the codes is a private thing that is used, there just to move the active code to the next place.

14. Root Aggregator and Event Handling

Short description:

The root aggregator is the main entry point to the domain, ensuring consistent state changes. It aggregates all the domain objects and provides a single point for making changes. By using the root aggregator, we prevent unexpected behavior and maintain the necessary steps for changing the domain. The root aggregator is shared within all events and is sent along with each event to subscribers. This allows subscribers to extract the necessary data from the domain to complete their actions. The root aggregator also includes a logger for easier event tracking and debugging purposes.

Any questions? Yes. Yeah, I have one. What does it mean? Root aggregator. I mean, why are you called it a root aggregator? So, root aggregator should be the only entry to your domain. Because, for example, if you can access your domain directly to a code and change it, then you will not have consistent state. Because your domain... So, you have to have a way to change your domain in a single point. If you have like your aggregation of your codes, your characters, your whatever you have there. What do you have here? Time stamp. Okay, we don't have this. If you go directly to the characters, and you can, well, you could, if you're not freezing it. We are freezing the object. But if you are changing the thing directly, you're somehow creating unexpected behavior because there's rules here. For example, when you set a value, there's multiple things that you have to do. Like you have to update the call time, and even the current time stamp. So if you just change the time stamp here, your domain will be corrupted because you're not filling all the steps necessary to actually change, to vote on the character. So that's why we have the root target, to be the only point that we do stuff. So if you go to our, I will show you. So the name, root aggregator means actually, main entry point something like this, or the collector of all the domain objects. It's like, okay. Yes. So this is what it aggregates. Yes. You could interact with the other entities directly. It's highly recommended by domain driven design because we're creating consistencies. If you have to do it, do it with very careful attention, right? Because in the past we burned ourselves, if you can. Okay. Thank you as a reason I will show you why we have this as well. Okay. So it created root aggregator. This is our domain. Let's call it like our entry point to our domain. And this will be shared within all the events or the events that we trigger, they will have it. So we have this root aggregator that basically is a bus decorator that in each event that is emitted we will send the root because for example, go to the use actions, use actions. So they use a click on this character. So I send this character because we click on it, we need to know what will happen is that who is actually subscribing to this thing, we'll get the root as well, the root as well. Why? Why? Let's start with the easy one. For example, on page ready, we will send the root automatically. The first thing is because we rely that the root will be there all the time. So we can project or get them with the correct word. We should do like getters, getters of information. So I need to know what is the runs that I am on because I need to track. So they used to click new game and you want to do analytics track. Okay. And they need to know that you are doing your game and you are in the wrong file. So you send your domain to all the events if you need to extract information to complete your action. Because otherwise you will have a very complex payload for the events and you want to make it as simple as possible because it should be the responsibility of the subscribers to know the domain and actually extract data from that. If you have to prepare the data every time you extract an event, then you will start to extract data in different places and in a way that the people that are listening that doesn't need. And this is one of the points here. When you meet an event here is the difference between a observable pattern and per-subscriber pattern. Here, the emitter have no idea who's listening. Okay, in observers, the observer knows that someone's actually there. Here is no idea. So is this the broadcast? Like a radio? I'm talking, I have no idea if you are listening. So that's why we sustain the route here to be able to get the data that they need. If they can't, it's because our domain is not complete. And for example, here we need to send access. Okay, so we decorate our bus event with this information and with the logger. Why the logger? Because if we check here, all right, each time we do stuff, like here, I know that what is happening, sorry, can I make it bigger? Plus plus, plus. Damn it, wrong one, plus. All right, so each time something happen in my application, I can easily follow the events. So let me refresh. So the page was ready and application loaded again. Okay, I click here, I see the UI click and application evaluates the answer and so on. So this is just for debugging purposes, it's easier to follow what is happening in application. So this is inspired on the query command simulation pattern. So where someone triggers a command query, we're getting someone else does a command but is not followed by the book because it's a little bit too much in my opinion. All right, so what else are we doing here? So and then we set up stuff. So for example, if I want to try my applications, the tracking is not working anymore. So this is just a single point where you can set up.

15. Application Setup and Event Handling

Short description:

If you don't set up the application, it does nothing. You can condition if your application will have audio or not in a single place. The reducer maps events to actions. Unfortunately, in this solution, we need to tell the UI what it needs to know. This is for performance reasons. If you don't care about performance, just put star and your UI will try to reduce everything.

Of course if you don't set up the application, the application does nothing, so it'd be useless. But if for some reason, this is not the case but the audio that we'll do next, you can condition if your application will have audio or not in a single place. So your infrastructure, according to some infrastructure condition, you can launch your services or not. Still confused? All right, so we set up the infra in our use application. And then she's our use actions. So your audio transactions is what we were working before, but with a difference that now they are super dumb. Okay, just like that. And here is a trick. This is the part that I don't like but in react I didn't find a way that makes it simple. So if you go to our reducer, our reducer is doing stuff according to some events. Okay? And if it doesn't know just return whatever it was before. And, but we are mapping the events to actions. So we need to say we have a list of things that we want our user to be able to use. And we want our UI to be listening to. Actually, we can be listening to ourself. But, okay. So what I mean is when one of the services or whatever, application, or when the application in our case, so far, does something, how do I need to react to it? Yeah, so like the game was loaded. No, so the application went to load application, the date that we need to load it. So this is a way that we have to glue the services and the UI, okay? So here, if you see, so we are going to all the events and we are subscribing. So when this happens, I will dispatch something, okay? We are making it into the loop. Maybe if I show the thing here. So we are getting this action to go to the resource, so we're creating this arrow. Otherwise, the UI will never repaint this stuff here, okay? So if you do anything in our application that your UI needs to know, unfortunately, in this solution that we are studying today, we need to tell it here, okay? It's not pretty. Would be nice if you do, like, sorry, you can just do, it would be nice. You don't need to do anything else, just this, but then your UI will run the reducer in things that doesn't concern. There's actions that your UI may not be interested on, and you will have a render, a re-render in this case, without reason. So this is the performance reasons. So if you just don't care about performance, just put star and your UI will try to reduce everything. Of course, it will not use anything, because it's not here, but this will cause every render.

16. Application Flow and Architecture

Short description:

In this step, we aim to get rid of unnecessary code and streamline the application's flow. We want to create a game when the page is ready and track page views. Chaining subscriptions can be problematic, so it's important to use them wisely. It's also worth noting that this architecture is not specific to any framework or tool. While there may not be specific boilerplates for this pattern, it allows for easy plug-and-play of new features. The codebase itself, like Next.js, can implement this architecture. The DDD pattern is a business-oriented approach to solving problems.

All right, questions? All right, so we are almost there. Okay, and that's it. And then we send actions and the state back. And our container is those actions that it was using before and uses our state as it was using before. So this is just creating the shortcut for our deep tool to our services. Yeah, so I will let you play. I will start the timer, so let me know if you have any questions. But the intent of this step is to get rid of this code here, all right? So you have a friends app that is here and I never, yeah, somebody providing you the use case. So we probably should show you something before, so. Sorry, can you say again, the purpose of this step is to get rid of this, for example, the moment, the UI is still, for example, fetching data, do it, doing tracking and emitting an event with a response of the action, okay? So we want to do something like this. Someone, someone is intending to start the game somehow, okay, and I think that is here, okay. When the user clicks on the dialogue, we need to do something. It's already done, this part. Set up. If you see our setup to our application, we have it here, so we're saying, when our application is ready, that is here, we create a game, and we emit an event, all right? And I can even do it better. So the application say, when the page is ready, I will create the game. That basically is fetching the characters, the codes, and everything and set it up. And it's, okay, the application was loaded. And the tracking is doing the same. When the application is ready, I will track page view. So you can attach multiple services to the same intent. Okay, so in this case, we only have two application in particular. So we have two application and tracking but we will start that more. The hint that they give in the beginning is to build the application around the domain and not the frameworks and tools. But that's precisely, if you take a look here, we can actually almost see, it was just a console. But like a product owner would say, so if you refresh, so the application, the page was opened and we start the game. Okay, probably this event shouldn't be game-loaded, it should be game-started. So this is like a description of a feature should be. For example, and then you go there, when the user clicks here, when the user clicks in one character, you validate the answer. Again, probably the name of the events are not the best because I didn't have a product owner to design this. Okay, but the idea is this is how it is, so when the user clicks, we do something. So this is the flow and you were saying that many things can be done at the same time and they are and they are not here. Probably that's what you are asking, but the tracking. Yes, right, you know, it could be like using the user who are speaking on something and that's what we were doing. In the other place, we try to update something and we send another notification to the back way like we send to the app notifications and it could be like a recursion because I'm accidentally send a message and what I'm already subscribed and how to do it programmatically to try to solve it. So one hint will be like each time that you call something like this. So if you inside of an subscription and you do another subscription, this is a smell that something is getting strange. So I keep trying to try to chain the subscription inside of subscriptions, you may face this issue. Please use like chain subscriptions wisely because then it will be very hard to follow, you're right. But that's like a callback help. So it's not much different, it's just a way of putting the stuff. I think I have something to hide here, but you want to help? Yeah, we had this example actually in our code base, which is an event that depends on another event. And this is just because our code was wrongly made. Chaining is okay, but yeah, as Samal said, it can be hecky to understand and to stop it afterwards and so on. So yeah, just make it wise you need to do it. Yeah, probably the takeaway from it is if you have to chain, probably something was not well designed because it shouldn't be many cases where you have to chain. So take a double look while you're chaining the other events. Okay, thank you. So I'm about 30 seconds late. Right, so, how was the round? Everyone was able to finish or save? Because Denny's was first. I'm quite new to this and I think I like the VM experience so far with the enums for the events especially. That was really cool. I have a question, so is this something that it's this growing in architecture. I think you can find it across frame like Angular or something like or is there some boilerplate of this which is maintained somewhere or just like just a question about this sort of accordingly in genre? Not really, I have an interesting comment here in the readme. DDD is a business part pattern. So this is not a software pattern but we are solving business issues, problems. So why not follow the same strategy? If there's boilerplates to start this, I don't know. We kind of create this boilerplate because it's fitted our needs. For example, you can go straight away skipping the event plus and use the application directly but then you'll lose the chance, we're not close, but it will be harder to plug and play new stuff on top. Like you want the tracking, you want the audio, you want a feature on a test, just plug and play. But if you're not comfortable with all these events going here and there, you can just do the normal application and execute stuff. Telling about the plate, I don't know. That's why we, in one of the previous answers you mentioned that this is used in this sort of architectures used in next year, summer. So I was wondering what is the commonality like the next year's framework uses this sort of an architecture or next year's codebase itself. Yes, the codebase itself. So I didn't, I'm not sure if they are using the DDD, but when I was searching for Leap to do the public subscribe, I was checking if we already using something in our code base because I didn't want to create another one. If you're already having our dependencies, let's use it. Otherwise I'll create or actually search for something that will help me to create the event. And I figured out that the meat that we are using here was the dependencies of the peer dependence of next JS. So somehow next JS in their implementation are using posts to subscribe to the job.

17. Using Posts Subscribe and Providing Quotes

Short description:

So it's not very uncommon to use posts subscribe. I have two links here that I can share. Use the posts subscribe to communicate, but that's two different things. In the setup app file, specify the quotes. If you don't wait, the quotes will not load. We were expecting you to provide the quotes. You can send it as an optional payload.

So it's not very uncommon to use posts subscribe. Actually I have two links here that I can share. Yeah, that can be because next JS has this elementary inside where you want to track certain business listing about our usage. Yeah, I think so. So I shared two links in the chat about possible usage of publish and subscribe. Maybe it can help you guys to find more ways of using this strategy. So it's one thing, DDD is another thing. So use the posts subscribe to communicate but that two different things.

Perfect. I will definitely recommend a boilerplate along with if you can bring up some of that. I can share with you the boilerplate that I can track something like that. Thank you. Cristian? Yeah. Can I ask you if you can run quickly, fast, let's say through the event in the sense in the use action file. Okay. This is very clear. You admit a new event. Okay. Very likely you're going to intercept this event in your setup upper. Correct. Okay. Okay. You have a function load new game. Okay. Because I think I did something wrong. I reuse the start game, start new game or probably, okay start load new game. Now what happens inside the load new game? Okay. My question here is, do you need to return the quotes so that you can pass it to the, I mean, the event that originally was in the UI? Why not? I was expecting you to return some how quotes from this method. Well, sorry. That's a very good question. So why you went out to return the quotes back. So somehow it goes in the same direction of something I was explaining before why we are putting the route in all the events. Because if you send the quotes here in this payload, so like this, if you use action, this action, sorry, this function will send the quotes, this function will send the quotes in the characters. This send the banana, this one will send something else. So we are making the payload too dynamic. So it means that the consumers of the bus have to know, so the case, it's very good to show. They will need to know, sorry, types. They will need to know and different payloads. So you could send it here. It could send you the quotes. I don't know if this is the event, but it could send the quotes, but the quotes already live inside of the root. Everything is there, so it simplifies. Everyone will read your payload in the same way because it's the same domain.

Okay. So this totally makes sense. But on the other hand, I had a problems in the setup app file. I had a problem because how can I specify exactly the quotes here? If you could set up... Okay. Probably you were not waiting for that response. So if you do this, if you don't wait, the quotes will not load at all. No, no, no. I was expecting here that emit up new quotes loaded. I was expecting it to have a payload, but I think still needed. Because if I add the quotes, that's the reason I returned the quotes from the loading game. So what we're saying is that we were expecting that you would provide the quotes here. Yeah, instead. Because otherwise it's apparently it seems different from the original code. You could send it. It, but.. But what you mean is that if I don't send a payload, anyway, it's in the route, which is automatically. Okay, this was not clear. Yeah. So you can send, I can even actually put it here as an optional if you want to override it for some reason. No, okay. Probably, it was not clear to me. Okay. It's very, very interesting to ask. Thank you. Yeah, it's much much clear now. Thank you.

18. Separating Layers and Setting Up Audio

Short description:

We discussed the possibility of separating layers from the main thread to improve performance. It is possible to run the app in a different worker, which could be beneficial for expensive computations that may block the UI. However, we haven't encountered this issue so far. In step three, we set up the audio to play only for Mortal Kombat when the game is finished with all correct answers. Any questions?

Thanks so much. And by the way, very clever, very clever solution. Yeah. Yeah. We faced this issue in the past, and that's why we start to running it here. Yeah, cool. Thanks so much. Any other cool question?

Yeah, I have a question. Would you recommend separating the layers from the main thread? Or around? I don't know. That's cool. Actually, we have a very interesting problem that occurs in the domain, but we didn't find the solution for it yet that is about resizing images and stuff that will be very interesting if you could do it there. But yes, you can, well, let me go back here, give me a second. Because the app uses domain straightaway, no, but it could extract the app to a different place. Everything that could be in the server. No, your setup, instead of using the app, could just be doing a call to the server. So this could be a, like in 1995, where there was no JavaScript and we're going to the backend. Yes, it's possible. So it can be running in a different worker. Worker, for example. Could be. And now, because we have the reference for the objects, it should be okay. I don't see any issue. If you have, what are you trying to solve? Trying to improve performance? Yeah, I was thinking of like expensive computations or something that would block the UI. Yeah, this will easily allow you to do that because we're not touched to anything, especially the app. Everything is injected. Should be all right. But we never had the issue so far. So, I see it perfectly doable. Thanks for the answer.

All right, oops, 10 minutes left. All right, so, let's keep going. So, I hope you like this exploration of how to travel in events from one place to another. Now, there's no audio. If you try to play your application, the audio is completely broken. That is sad. So, we will try to set up the audio. Quite independent. If we go to our step three. Probably some of you are already on the step three. I don't want to throw away my work. Here, check out step three. What to add? So we'll have to grab our use actions file. So again, use our use actions file and we have all this use comment code here in the bottom that before it was in action and we remove it. And we want to make it a separated piece of code, completely isolated. So we will set it up. I can't create the set up problem that doesn't exist. So source infrastructure value is a file that OK. So that that we are already trying to execute here. Michael is also this complaint. So we already trying to do a set of value. We just send the bus and it has to do everything else. Christian, you hand up some. So and the really good yeah. You have to subscribe to what an answer is validated and when the game is finished. Have you. I don't know if you notice that we have here a code that it is. What are you eating? That only works for Mortal Kombat. For Mortal Kombat, by the way. And it's gone. What happened? Looks like progression, but you can do it. OK, good. It's not there. So the thing is, if when the game finished, that's why we have this subscription. When the game is finished and all my answers are correct, I will play the audio only for Mortal Kombat flawless victory. So there is a audio there that you have to play it. Any questions? Yeah, sorry, I was a little bit distracted, can you say the conditions under which we play the Mortal Kombat 5? OK, so the first one is like the user, which end of application, while it's an answer, we should play yes, no or the character should play us not according to the AB test. The code is somewhere here for that one. Location. Yeah. So if it's Mortal Kombat play something.

19. Playing Announcements and Moving to the Next Round

Short description:

If all answers are correct, play the flawless victory sound in Mortal Kombat. Set up audio based on the game being in Mortal Kombat or not. Discuss feedback and move on to the next step. Step four is about playing announcements after each round. Open the file and add the new event for this logic. Jump to the next round when the game is finished and announce the start of the new round. Only play the sound for Mortal Kombat rounds. Timer set for 10 minutes or less. Check out step four.

If it's not play something else, be wise to do it. Maybe you shouldn't do like that. I will give it to you. And then there is another event that the app triggers is like the game is finished, the round is finished. So if all the answers are correct, we will play the flawless victory if we are in Mortal Kombat. Oh. OK. I will do it here maybe I'll try to do it very quiet so I can. And in your side as well, but if you want to follow. That's if I still remember to do this. So I will do, instead of having like all these in his case, I will break it straight away here. But you can keep the same strategies. I think it's slightly cleaner. So when I set up my audio, I just say, okay, I'm in Marco Combat, okay, so I'll set up this audio. I'm not. So I'll set up the other one. Sorry. No, no, no, no. You are totally making this up. You are totally making this up. Okay. Should be, and give it a trick try. So if we have an answer and it is correct, all of them are correct. Let's try. So, oh, damn it, wrong variance. Do you know what to change the variance? So you can just do cookie store.set AP panel and just change the stuff. Rob does. Rob said something. So, Rob's… Well done, Brutal, Brutal, superb, Brutal. Well done, very good. So, what was good, what was bad? What would you do different? 15 minutes was too short, was too much. So I ran out of ideas. Probably. this up. Focus on the okay. Anyone has any questions about this? No, okay. So let's move on to the next thing. And then we have a break. All right. Step four. Play around announcements. So basically it's built on top of this one. Good. I think — one more time, I'm sorry. So, after each round — so, when the game starts, you play round one, and then each time the next one, round two, three, four, five, and six, because we have no more audios, each time after, we'll play five. All right? Yeah, so you open this file, and just add the new event to do this logic. So, it will be something similar, like this one — let me see. So, this is — yeah, when the game is finished, you have to check if everything's okay. Oh, it's here. Oh, don't look! Okay. So, when the game is finished, we have to jump to the next round, basically. Yeah, it's jumping. Yeah, and we have to announce that we are starting the new round. No, no, yes, we will play this sound, for example. Yeah, yeah. Round two, round one, round three. Again, this is only for Mortal Kombat, so I think it will make no sense to play this one. Can I just ask you, do we already have in our rounds round number? No, it's a new thing. Okay. Good, we already helped everyone. It's good, it's good. I'll set the timer. This one is quite short, so 10 minutes should be all right, or even less. First one to finish, raise their hand. We'll set the speed. Three days later, we are here. What is the step? Same roll. Sorry, I'm muted. Step four. Check out step four.

20. Creating Lobby and Typed Events

Short description:

We created a new property in the network aggregate called round, which is incremented each time a new game is started. We added an onGameFinish event for the game over announcement and waited 2 seconds to avoid overlapping with other sounds. The round number determines which audio to play. Some struggles mentioned were adding the plus one to the round and an error in code 63. Naming conventions and aligning with the product owner's language were discussed. The suggestion was made to have the product owner create use case files with descriptions of events. Typed events were mentioned as a way to make code navigation easier.

It's from there. I will do it here. Sorry, if you don't want to follow. Don't make me laugh. Surround it after 7, fight all the time. If it's not...ưng it's over that what are you waiting for perfect timing yeah definitely anyone want to share the progress Okay, I will share. So, we have time for the animation. All right, so what I've done here, like Kristen was asking, we don't have this round information on the root aggregate. So, our domain doesn't know this and it should. So, what we have done, we created a new property in network aggregate, it's called round and it's started as whatever we start for zero. And then each time we have a new game, I incremented the round, right? And what do we have here? The network aggregate has the name cell, it's concentrated on State Nu, it's incremented every time we start it. And in the setup of the audio, so we add this onGameFinish, we will do a game over announcement. And I waited 2 seconds, because otherwise I will overlap with the others before, so to give some time to the other guy to talk, and I'm showing the wrong code. And... I wrote the announcement, sorry. So, yes, that's exactly right. Exactly, so whenever you code, so when you have new data, I will shout. So basically, when I start, when I create a new game, or when I click a new game. Maybe I should put here some comments, or rename those events. And so I will get my round from my root. And if the round is smaller than 7, I will play the wrong number, otherwise I'll go to the fight version of it. So how far you guys were? What was the hardest part to figure out here? Anyone want to share some struggles?

Same as before. I was trying to do that, that is to add the round somewhere in the root, but then, I was not... At the very beginning, I didn't know how to add the plus one. So I was not sure if I had to add it here or use in some other events, but this should be enough, I think. Yeah. And by the way, I think you have an error in your code 63. Because round is a number it's not... Yeah. While the audio files are named after the letters which compose like audio one. Are they? No. Okay. I saw that there's an error. Okay. Sorry about that. Misunderstanding. All right. Cool. Thank you for sharing. So let's see what we have next to do. So create a lobby. So what is this lobby situation? So let's go to step five.

I'm sorry, Samuel. Also I want to add some my thoughts about... For me, the hardest part was to understand should I create new event for exactly this step or should I use existing one. So I decided to use this, also UI event to quick start new game. But I don't know. I'm not sure because it's like not the implementation or release event for this event. I don't know to explain that. Yeah, I understand. Maybe I said in the beginning here, game.loaded. Probably this will not be what a product owner will say. Probably this will say application game created, okay? Maybe here it will make more sense, yeah. And here as well, new codes loaded. Maybe not, maybe like new game started, okay? Yeah, see that the naming of things are probably the most important things in software engineering. So if we align these things with our product manager, product owner, probably those names will come by cleaner for us because we developers tend to do this kind of stuff and then we don't understand ourselves. So if everyone stalks the same language, it will be easier. So probably that's why we have this issue to try to figure out where to put this. Yeah, that's why I was asking before about use cases and the storage to domain because I understand it is not for the main part but like product owner, he can create some file with the use cases in the regarding them So maybe we can just put a constant here and use them. And it will be like new slides if we don't know what kind of, I do not know one moment. I lost my thought. Okay, never mind. I said that the product owner can describe those events and we can easily follow them if we have those cases. Yes, I think it will be better if somebody who's not a developer will create them because we tried to create them like, I don't know, yeah, I used something here, et cetera, like React minding. Exactly. Don't underestimate your product owners. They know what they're doing. Thank you for sharing. Sorry, can I ask you something which is not specific to this one, but more general? Is there a way in your opinion or in your experience to use typed events instead of strings so that it can be easy to navigate to the code, for example. Instead of strings.

21. Typed Events and Lobby Feature

Short description:

They discussed the benefits of using typed events and the possibility of using objects or enumerations instead of strings. They also mentioned using symbols or functions as identifiers but found it confusing. They decided to use strings for namespacing. They then moved on to discussing the lobby feature and the need to add a dialogue to ask the user to start the game. They provided instructions and examples for implementing the dialogue. They mentioned that animation would not be covered in this workshop. Finally, they discussed changing some events and the solution for showing the dialogue without changing the flow.

Actually, they are kind of typed because we define them here. So if you try to call this event with something that doesn't exist, it will fail. So if you try to get that. I agree with that, but let's say that I want to see where answerValidate is defined, I have to look in the code, do a string search in the code. Do you think is there a way or maybe the question is, do you think it can be beneficial to have like objects or enumeration? It can work first of all or not? And we can even send a symbol here that will allow you better to unsubscribe from the event. You can send whatever you want. We can even send a function as an identifier. But I'm not sure if this is easier to identify. To be honest, I worked in a project in the past that they were using functions as the ID of the event. And they can even take advantage of that and execute at the same time. So it was quite confused, I didn't like it. So that's why this time I decided to use strings because we can create namespacing here, or we can create it with objects, as well. I don't have a strong opinion. If someone has a clever way, please share with me later. Quite interested to improve. Just curious, thank you. You're welcome.

So we are running out of time, but we still have time to finish one more. This is probably the most useful feature that this game needs. That is the lobby. Let's go to lobby. Because at the moment when we use our application, the game starts right away. And this is a little bit annoying. So we will add a dialogue asking the user to start. So the same stuff. Let's go to the step five. And we have some, I'm sorry about the sound is here. Not sharing with you, but read me. And we have some instructions there, as well. So there is the content to put on the dialogue. It can be creative, but I provide some suggestions. And we have an example of the dialogue already in the game container, TXX. So we will need the another dialogue that will be shown only if the game didn't start. And when there's a click, we actually start. Right now the game is starting automatically and ready. So we need to change a few things to make it starting and ready and start only when the user clicks on that button. And I think should be the last exercise. Unfortunately animation was the coolest one, but I don't think we'll be able to do it. So, this one here, what I will suggest is to change some of the events because they don't make more sense anymore, especially from the UI. I was hoping that the existing Start Game Click could do the trick that you're suggesting to use. Yeah, we can still use it. But then the name doesn't make much sense. So what I did, I broke into... We'll need one new, because it's a new start that way we have a new interaction from the UI. But then we'll conflict a bit with what we have. Let me show the default file. I'll type done. Yeah, so I have a play again and start playing. I think it makes more sense. Anyone manage to show the dialogue even if it's not changing the flow? Oh, cool. So, do you want to share what was your solution? I was trying to load the text at the moment. Denis, what was your solution? I don't know because it was a little bit tricky. I didn't delete any old events, I just added. I changed the initial state attribute, what's called this GameOver, to like sink attribute, which the name is just dialogue state. The dialogue state is have three different states. Like welcome state, end game, or play a game state, and hide. Depends on the data loading, I spam the information, but it should be a welcome state, and this trick, it works. Okay. So we're using the same. What you are stopping the application on the screen. Right. OK I can share them what I've post more or less. I really would like to know it. That should be pretty similar to what is in the in the Git. Thank so much for your input. OK, thank you.

22. Game Flow Changes and Challenges

Short description:

We made some changes to the game flow and added a new dialog for starting the game. The challenges include creating a Dan animation and changing a character's name. Unfortunately, we don't have time to finish these steps, but you can complete them offline. If you need help, feel free to reach out. Overall, the workshop provided valuable insights into separating UI and business logic, and the benefits of using PubSub over Redux for performance. Thank you for attending!

All right. So between different directions here, but the one I found which really agree with 진짜 everything she said with me, it's going to be a change for I think something, I think she's going to take a little bit more time. Let's see. Let's see, it's my fault if I put this one my, my thought is let's go from round to round. And then, you know, for tax, we get into any thing, I just I was doing the extra step that was having held it for a lot of time. It was not part of this task.

And then so when you click start again, this is not in a page anymore. It's on start a game. And with what was doing before. And we have this new one here, actually, it is the same with every name. Exactly. So when play again, it's loading. So basically, was shuffling it to the data. So the game is not starting anymore on the page ready, but is on the when the user actually clicks on something. More stuff, so to get the same stuff, I will track the game click on a different event. And I took a different approach of them is I have literally created a new dialog, that I show only when I have codes. So I am assuming that if I have codes, the game is ready to start. Maybe it's tricky. Maybe it's not. Tell me what you think. So this was the solution.

Okay. So we had two more challenges for you, but you can complete offline and you can click your fingers to get some help. So one of them was doing the Dan animation. So as I show with like the Mortal Kombat gentlemen that comes from the side doing the jump, you can even have an illustration here for step six. And... oops that was the last one. So what is the link to this animation? So when you have a combo on top of the sons, we have this gentleman coming. And in case of control version of actual net instead, you can, can try to do it. I just stop a tip to make you a bit more harder. Maybe this route, previous call to step seven, this code can help. So it's time to send them on change. It can, can, can try to see if it's a combo or not because the previous code will tell it, this is a comb. So it can just react. Um, something else that I like to challenge you is something quite simple. Um, so the step seven is the last one. That is, um, this name is stupid. No, no one knows who is Joffe's Francis in the game, the TV show, everyone knows him as Joey. So the feature is actually used as shortness. It's very simple just go to the response and change the value on the character, um, I hope you'll still have fun with this after the workshop. But unfortunately now isn't time to finish these two steps. I hope you can finish by yourself. Um, just reach us if you need some help to actually finish them. Any questions? I just want to say that it was very, very interesting. Thank you. I'll say it's maybe slightly different that we are used to do in applications. Yeah, because sorry, my dog. Uh, yeah, because, uh, you know, it's a common since principle to split the UI business logic, but sometimes, especially in the JavaScript, you don't know how to do it. So this is, uh, they're very good to hints. Yeah, I can add on top of fuel. Like, since I started in front end, I used to. I have this comment a lot. This is business logic. Shouldn't be here, but no longer we should have business logic. No one ever told me where it should be. So it's stay there until until very recently. Um, yeah, this is a very common thing to do outside of the front end world. Front end development. This is all software development. So we should still use the same patterns and the same principles. Definitely. So how will you start modeling your domain? How would, well, you actually think that's worth it to move the stuff off of the Y for all the applications or just for large applications or for none at all? Actually, I tried to prevent this domain dream design. The thing is, like, to separate for NT and App and other things. But in this break, Redux does a lot of work for you and I tried to change it for more like your way of stuff. And in our company we have one really big application, the Redux was really slow. And after we changed it to PubSub, it's performance increase. So thanks a lot, because like, for me this practice, because we try to implement it in our own way. We know like one silver bullet for everything. And that's why when you share your knowledge now, I know a little bit more. About how we can do it, how we can implement in our services. So thank you again. You're welcome. Okay. That was all that I have, probably I was, expecting to finish, but, yeah. That's good. I really enjoyed it.

Watch more workshops on topic

React Summit 2023React Summit 2023
170 min
React Performance Debugging Masterclass
Featured WorkshopFree
Ivan’s first attempts at performance debugging were chaotic. He would see a slow interaction, try a random optimization, see that it didn't help, and keep trying other optimizations until he found the right one (or gave up).
Back then, Ivan didn’t know how to use performance devtools well. He would do a recording in Chrome DevTools or React Profiler, poke around it, try clicking random things, and then close it in frustration a few minutes later. Now, Ivan knows exactly where and what to look for. And in this workshop, Ivan will teach you that too.
Here’s how this is going to work. We’ll take a slow app → debug it (using tools like Chrome DevTools, React Profiler, and why-did-you-render) → pinpoint the bottleneck → and then repeat, several times more. We won’t talk about the solutions (in 90% of the cases, it’s just the ol’ regular useMemo() or memo()). But we’ll talk about everything that comes before – and learn how to analyze any React performance problem, step by step.
(Note: This workshop is best suited for engineers who are already familiar with how useMemo() and memo() work – but want to get better at using the performance tools around React. Also, we’ll be covering interaction performance, not load speed, so you won’t hear a word about Lighthouse 🤐)
React Summit Remote Edition 2021React Summit Remote Edition 2021
177 min
React Hooks Tips Only the Pros Know
Featured Workshop
The addition of the hooks API to React was quite a major change. Before hooks most components had to be class based. Now, with hooks, these are often much simpler functional components. Hooks can be really simple to use. Almost deceptively simple. Because there are still plenty of ways you can mess up with hooks. And it often turns out there are many ways where you can improve your components a better understanding of how each React hook can be used.You will learn all about the pros and cons of the various hooks. You will learn when to use useState() versus useReducer(). We will look at using useContext() efficiently. You will see when to use useLayoutEffect() and when useEffect() is better.
React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Featured WorkshopFree
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.

The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.

React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.
React Summit 2023React Summit 2023
151 min
Designing Effective Tests With React Testing Library
Featured Workshop
React Testing Library is a great framework for React component tests because there are a lot of questions it answers for you, so you don’t need to worry about those questions. But that doesn’t mean testing is easy. There are still a lot of questions you have to figure out for yourself: How many component tests should you write vs end-to-end tests or lower-level unit tests? How can you test a certain line of code that is tricky to test? And what in the world are you supposed to do about that persistent act() warning?
In this three-hour workshop we’ll introduce React Testing Library along with a mental model for how to think about designing your component tests. This mental model will help you see how to test each bit of logic, whether or not to mock dependencies, and will help improve the design of your components. You’ll walk away with the tools, techniques, and principles you need to implement low-cost, high-value component tests.
Table of contents- The different kinds of React application tests, and where component tests fit in- A mental model for thinking about the inputs and outputs of the components you test- Options for selecting DOM elements to verify and interact with them- The value of mocks and why they shouldn’t be avoided- The challenges with asynchrony in RTL tests and how to handle them
Prerequisites- Familiarity with building applications with React- Basic experience writing automated tests with Jest or another unit testing framework- You do not need any experience with React Testing Library- Machine setup: Node LTS, Yarn
React Day Berlin 2022React Day Berlin 2022
53 min
Next.js 13: Data Fetching Strategies
- Introduction- Prerequisites for the workshop- Fetching strategies: fundamentals- Fetching strategies – hands-on: fetch API, cache (static VS dynamic), revalidate, suspense (parallel data fetching)- Test your build and serve it on Vercel- Future: Server components VS Client components- Workshop easter egg (unrelated to the topic, calling out accessibility)- Wrapping up
React Summit 2022React Summit 2022
160 min
React at Scale with Nx
The larger a codebase grows, the more difficult it becomes to maintain. All the informal processes of a small team need to be systematized and supported with tooling as the team grows. Come learn how Nx allows developers to focus their attention more on application code and less on tooling.
We’ll build up a monorepo from scratch, creating a client app and server app that share an API type library. We’ll learn how Nx uses executors and generators to make the developer experience more consistent across projects. We’ll then make our own executors and generators for processes that are unique to our organization. We’ll also explore the growing ecosystem of plugins that allow for the smooth integration of frameworks and libraries.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Advanced Conference 2021React Advanced Conference 2021
39 min
Don't Solve Problems, Eliminate Them
Humans are natural problem solvers and we're good enough at it that we've survived over the centuries and become the dominant species of the planet. Because we're so good at it, we sometimes become problem seekers too–looking for problems we can solve. Those who most successfully accomplish their goals are the problem eliminators. Let's talk about the distinction between solving and eliminating problems with examples from inside and outside the coding world.
React Advanced Conference 2022React Advanced Conference 2022
30 min
Using useEffect Effectively
Can useEffect affect your codebase negatively? From fetching data to fighting with imperative APIs, side effects are one of the biggest sources of frustration in web app development. And let’s be honest, putting everything in useEffect hooks doesn’t help much. In this talk, we'll demystify the useEffect hook and get a better understanding of when (and when not) to use it, as well as discover how declarative effects can make effect management more maintainable in even the most complex React apps.
React Advanced Conference 2021React Advanced Conference 2021
47 min
Design Systems: Walking the Line Between Flexibility and Consistency
Design systems aim to bring consistency to a brand's design and make the UI development productive. Component libraries with well-thought API can make this a breeze. But, sometimes an API choice can accidentally overstep and slow the team down! There's a balance there... somewhere. Let's explore some of the problems and possible creative solutions.
React Summit 2023React Summit 2023
23 min
React Concurrency, Explained
React 18! Concurrent features! You might’ve already tried the new APIs like useTransition, or you might’ve just heard of them. But do you know how React 18 achieves the performance wins it brings with itself? In this talk, let’s peek under the hood of React 18’s performance features: - How React 18 lowers the time your page stays frozen (aka TBT) - What exactly happens in the main thread when you run useTransition() - What’s the catch with the improvements (there’s no free cake!), and why Vue.js and Preact straight refused to ship anything similar
React Summit 2023React Summit 2023
24 min
Debugging JS
As developers, we spend much of our time debugging apps - often code we didn't even write. Sadly, few developers have ever been taught how to approach debugging - it's something most of us learn through painful experience.  The good news is you _can_ learn how to debug effectively, and there's several key techniques and tools you can use for debugging JS and React apps.