React Test Development Experience for Aviasales

Hi, I wanted to share my experience in developing a test task for Aviasales.







I recently stumbled upon a React developer job at Aviasales. I sent an application, after which the next day HR answered me and informed me that I would have to do a test task. I really do not like to do test tasks, since I have to spend quite a lot of time on their implementation, and in case of failure this will be wasted. But I agreed ...







You can find the test task here at the link .







Here is a link to my repository of the completed task.







I limited myself in completing the assignment in one day (although I did make minor improvements after publication: I finished the sketch, so to speak).







What I chose for development:







  1. I chose NextJS as the basis, because I didn’t want to tinker with setting up the environment for Webpack, and you can deploy the project itself with a couple of clicks.
  2. I wanted to write fast and chose the React-IOC package in conjunction with MobX instead of Redux. This is a package that allows you to write applications through services that resemble angular services.
  3. I used Web Worker so that there were no lags in the interface while sorting a large amount of data.
  4. I did not use Typescript for the purpose of not writing additional code with a useless waste of time on a test task.
  5. Based on paragraph 4, I also did not write tests.
  6. I added two additional packages to the project: debounce, RxJS. The first is needed to create simple callbacks, for example, changing the boot status so that the spinner does not show the download if loading takes extremely little time. I always use the second package to create an action script, for example, to process states in case of an error when sending a request to the server.


The procedure for the first stage of development:







  1. Initialized repository.
  2. Initialized NextJS project.
  3. Added an index base page with a Hello World message.
  4. Created a ticket.provider service that interacts with the api server.
  5. Created the ticket.service service, which injects ticket.provider and fills the observator with an array of displayed tickets
  6. Created ticket.filter.service, which stores filtered data injected from ticket.service via @computed


The second stage of development:







  1. Created components and painted styles for them using the layout provided in the task repository.
  2. I made a spinner of the download and put down its value from the services.
  3. Connected all service logic with components.
  4. Added utilities with data formatting, such as time and money.


Then I decided to try the “touch” interface and found flaws when using the application:







  1. There are interface slowdowns when changing the filter and sorting, so I transferred the storage, retrieval and filtering of data to Web Worker, after which the lags completely disappeared.
  2. Spinner did not fix the jumping line animation, so I replaced it with a visual display of lines with flicker animation.
  3. For ease of data rendering, I transferred the data formatting calls to Web Worker, this reduces the load on component rendering


Then I finished my work and at the end of the day sent a task for verification.







Since I limited myself in time, I did not optimize the application further, namely, I did not use React.memo (...). I also did not begin to replace window and router with injectors in services. Forgive me for this, this is a flaw.







But the next day I added the functionality of remembering the state of the filter in the browser url line, after which I was already satisfied with the work done.







I waited for a response from them for 7 days, they did not reply to any of my messages. It was an unpleasant experience, so to speak. But still they answered, and the answer was extremely distressing to read. The message can be seen below.







Let's take a look at the points:







[one]. “The work is done very carefully”







I don’t see where, not an argument, since there are no examples.







[2]. “It seems that the development pursued the goals of“ it works, ”and ignored“ how it works. ”







Not an argument, no examples.







[3]. “Based on our requirements for candidate levels, the completed task barely reaches middle.”







What are the requirements? Where are they?







[four]. “We expect that the filters will not be hardcoded and will adapt to the data. If you go to aviasales, you can see that the tickets are shown immediately as the first installment appears, and we don’t wait for everyone to load. ”







This requirement was not in the attached task. And the Aviasales application itself, in my opinion, does not have a reference interface, and jumping tickets is not the best solution.







[5]. “Why does filter.service know about router and window? He should not control the state of the application and have such dependencies at all. ”







Because the services are created to control the state of the entire application, or the module where they exist. Here the author clearly suggests writing all the logic in the components.







[6]. “Web Workers. What is the profit? In this case, a lot of time is spent on asynchronous operations, and the saved load in the main thread is spent on serialize / deserialize objects (and observable objects). If we are talking about optimizations, then it was worth starting not with removal in the web worker, but fixing the problems in the main thread. ”







How can I handle the processing of large amounts of data in the main thread and at the same time without interface lags? It will be extremely interesting for me to find out if anyone has an example, then write in the comments. Apparently I'm missing something.







[7]. “It makes no sense to add rxjs to the project just to implement retry and sequential loading.”







Why doesn’t it make sense? You can import strictly necessary functions into RxJS; if tree shaking packages and functions do not work properly, this will not increase the size of the application.







[8]. “The project cannot be scaled and maintained. Constructs like (ticket.segments || [{}, {}]).map((ticket) => ...)



very bulky. ”







Let's go through the criteria of scaling and support: accessibility (services solve this problem), risks ( ticket.segments || [{}, {}]



- this is just an example of how to deal with cases if input does not contain data. An example is bad, but the nullable structure approach at least, but I try to comply), clean code (well, at least I know what it is :), although I tried to write everything as expected). It seems that everything is captured, again not an argument.







[9]. “I got the impression that there is absolutely no understanding of how React works under the hood. There are many critical errors in working with props for components that have a very bad effect on performance. React optimization mechanisms are ignored. ”







I can’t understand where these described problems are. What kind of mechanisms?







[10]. “Creating handler functions inside render.”







I don’t have any handler functions in render at all, does anyone understand what is written here? I even transferred formatting processing to Web Worker







[eleven]. “Creating a new empty object and transferring it to the ticket. ticket-list-loading.jsx:10



or Ticket.tsx:24



”







There is nothing critical here, except for my laziness to take out separately the loading-ticket component. Passing an empty object does not violate any programming principle, except that here it was necessary to do this through ticket = ticket || {};



ticket = ticket || {};



but this is purely due to the fact that the development time was limited to one day and it would take more time to fix all minor flaws.







[12]. “Array indices as keys on a ticket list”







Here the question is rather why api does not return elements with id. Therefore, when receiving data from the server, I would need to generate unique keys for each element, which I did not do as part of the test task, since even in a real project this is a dubious approach.







And finally, the conclusion: “In general, React did not work (

Total: for the middle level, we expect that there will be no critical problems with react, but there are a lot of them in the work done. ”







There are already no comments ...







Thank you if you read to the end. I have a very negative opinion about Aviasales, so I post everything here so that you can evaluate yourself whether you should contact them or not.







Full text of the message:







The work is done very carefully. It seems that during the development the goals were “it works”, and “how it works” was ignored. Based on our requirements for candidate levels, the completed task barely reaches middle.







Performance and structure:

We expect that the filters will not be hardcoded and will adapt to the data. If you go to aviasales, you can see that the tickets are shown immediately as the first installment appears, and we do not wait for everyone to load.







Further, more technical points.







  1. Why filter.service



    know about router and window? It should not control the state of the application and have such dependencies at all.
  2. Web Workers. What is the profit? In this case, a lot of time is spent on asynchronous operations, and the saved load in the main thread is spent on serialize / deserialize objects (and observable objects). If we are talking about optimizations, then it was worth starting not with removal in the web worker, but fixing the problems in the main thread.
  3. It makes no sense to add rxjs to the project only for implementing retry and sequential loading.
  4. The project cannot be scaled and maintained. Constructs like ( ticket.segments || [{}, {}]).map((ticket) => ticket



    ) are very cumbersome.

    React:

    I got the impression that there is absolutely no understanding of how React works under the hood. There are many critical errors in working with props for components that have a very bad effect on performance. React optimization mechanisms are ignored. Briefly about the problems:
  5. Creating handler functions inside render.
  6. Create a new empty object and transfer it to the ticket. ticket-list-loading.jsx:10



    or Ticket.tsx:24



    .
  7. Array indices as keys on a ticket list.

    In general, React did not work :(


Total: for the middle level, we expect that there will be no critical problems with react, but there are quite a lot of them in the work done.








All Articles