📜 ⬆️ ⬇️

Social games: server, client and shared event bus

Good day.
I had free time, and I decided to write an article about the unfairly ignored pattern of writing api. It is suitable if you and the client and the server contain a complex state, and there is a need to synchronize it. In my opinion, social games are ideally suited for this description. Due to the fact that I have not yet reached that level of skill when I can write articles about programming without code, I hasten to provide an example demonstrating this approach. You can see the code on github: https://github.com/dbalakov/studio_game .


A few curtsies about the project. The writing style differs in production code, due to the fact that the goal is to demonstrate the idea as quickly and clearly as possible. For example, instead of using jake, you will have to manually install connect and node-uuid .
npm install connect npm install node-uuid 

Also, instead of using built-in sessions, there is a samopisny bicycle. There is no work with the database, but there is a wonderful article about this from mail.ru Databases in online games. From Allods Online to Skyforge , and you can easily and painlessly add a DAO layer to this project.
It is worth noting the complete absence of tests, but about testing in nodejs there will be a separate article.

I will try to build this article in the form of a stream of thoughts at each stage of development, so we will start with the statement of the problem and will gradually, meditation after meditation, implement the project.
')

Formulation of the problem


We are writing a game about game development. We have a project to work on, and then when we are ready to show the project to the world, we can sell it and start a new one. The project has 3 main characteristics: graphics, features, bugs and improving each of them, we can change the output cost of the project.

First meditation


The architecture of client-server applications is best to start building with api. This allows you to see both the client and the server, and, based on the statement, we get the following api:

After a cup of coffee and a careful look at this api, you can understand that it is redundant: init, login and sellProject, newProject - associated methods: after init, login is immediately called, and after selling the project we immediately start a new one - so we can combine these methods. After this, our api looks like this:

We will start the implementation from the server and, of course, from the model layer. What I did, you can see in the models folder.

Second meditation


If you look closely at your project manager, you will notice some sparks in his eyes: these are new, as yet unborn ideas and features, which then have to be included in the code, so to simplify adding new methods to api, we will remember the DRY commandment and understand what to duplicate A description of the methods on both the client and server is redundant. Let the init method return a list and description of the methods by which we will build the api object. What I did, you can see here: the implementation of the method on the server side . But it threatens with additional load on the server, and to reduce it, we cache the answer. Implementation on the client here

Third meditation


Let's try to present our future code. For example, what should happen on the client and server when a project is sold? We increase the player's money and initialize a new project, that is, something like this should be done on the client and on the server:
 player.money += projectCost; 

But during the previous meditation we already recalled the principle of DRY , and writing the same thing on the client and on the server is a clear violation of it. In order to simplify the code of the server response handlers and avoid identical lines in the client and server code, we will introduce an event bus common to the client and server, that is, the model on the server itself will monitor its changes and notify the client about them. On the server, model is responsible for this, and if you use setters in the code, and do not directly access the properties of the object, you will automatically receive the current model on the client.
On the client, an event handler can be written once, and in this implementation it does not even depend on the structure of the model.

Conclusion


After three simple meditations, we received a project with a “plasticine” code that is easy to read and expand. And if we have not 4 server methods, but at least 30 pieces, then we will get a gain not only in readability, but also in the size of the code. Therefore, I urge all colleagues to spend at least an hour or two to think about a task after a piece of paper before running to create a new project and quickly write code.

PS My cat did not like the first version of the article and she rudely deleted it, citing complete unreadability. I hope I took into account the errors, and the article became clear.

Source: https://habr.com/ru/post/188928/


All Articles