Hola, quería compartir mi experiencia en el desarrollo de un caso de prueba para Aviasales.
Recientemente me topé con un trabajo de desarrollador de React en Aviasales. Envié una solicitud, después de lo cual al día siguiente, RR. HH. Me respondió y me informó que tendría que hacer una tarea de prueba. Realmente no me gusta hacer tareas de prueba, ya que tengo que dedicar mucho tiempo a su implementación, y en caso de falla, esto se desperdiciará. Pero acepté ...
Puede encontrar la tarea de prueba aquí en el enlace .
Aquí hay un enlace a mi repositorio de la tarea completada.
Me limité a completar la tarea en un día (aunque hice mejoras menores después de la publicación: terminé el boceto, por así decirlo).
Lo que elegí para el desarrollo:
- Elegí NextJS como base, porque no quería jugar con la configuración del entorno para Webpack, y puede implementar el proyecto en sí con un par de clics.
- Quería escribir rápido y elegí el paquete React-IOC junto con MobX, en lugar de Redux. Este es un paquete que le permite escribir aplicaciones a través de servicios que se asemejan a servicios angulares.
- Utilicé Web Worker para que no hubiera retrasos en la interfaz al ordenar una gran cantidad de datos.
- No utilicé Typecript con el propósito de no escribir código adicional con una pérdida inútil de tiempo en una tarea de prueba.
- Basado en el párrafo 4, tampoco escribí pruebas.
- Agregué dos paquetes adicionales al proyecto: debounce, RxJS. El primero es necesario para crear devoluciones de llamada simples, por ejemplo, cambiar el estado de descarga para que el control no muestre la carga si la descarga toma muy poco tiempo. Siempre uso el segundo paquete para crear un script de acción, por ejemplo, para procesar estados en caso de error al enviar una solicitud al servidor.
El procedimiento para la primera etapa de desarrollo:
- Repositorio inicializado.
- Proyecto NextJS inicializado.
- Se agregó una página base de índice con un mensaje de Hello World.
- Creó un servicio ticket.provider que interactúa con el servidor api.
- Creó el servicio ticket.service, que inyecta ticket.provider y llena el observador con una serie de tickets mostrados
- Se creó ticket.filter.service, que almacena los datos filtrados inyectados desde ticket.service a través de @computed
La segunda etapa de desarrollo:
- Componentes creados y estilos pintados para ellos utilizando el diseño proporcionado en el repositorio de tareas.
- Hice un spinner de la descarga y bajé su valor de los servicios.
- Conectó toda la lógica de servicio con componentes.
- Utilidades adicionales con formato de datos, como tiempo y dinero.
Luego decidí probar la interfaz "táctil" y encontré fallas al usar la aplicación:
- Hay ralentizaciones de la interfaz al cambiar el filtro y la clasificación, por lo que transferí el almacenamiento, la recuperación y el filtrado de datos a Web Worker, después de lo cual los retrasos desaparecieron por completo.
- Spinner no reparó la animación de la línea de salto, así que la reemplacé con una visualización visual de líneas con animación parpadeante.
- Para facilitar la representación de datos, transferí las llamadas de formato de datos a Web Worker, esto reduce la carga en la representación de componentes
Luego terminé mi trabajo y al final del día envié una tarea para verificación.
Como me limité en el tiempo, no optimicé más la aplicación, es decir, no usé React.memo (...). Tampoco comencé a reemplazar la ventana y el enrutador con inyectores en los servicios. Perdóname por esto, esto es un defecto.
Pero al día siguiente agregué la funcionalidad de recordar el estado del filtro en la línea de URL del navegador, después de lo cual ya estaba satisfecho con el trabajo realizado.
Esperé una respuesta de ellos durante 7 días, no respondieron a ninguno de mis mensajes. Fue una experiencia desagradable, por así decirlo. Pero aun así respondieron, y la respuesta fue extremadamente angustiosa de leer. El mensaje se puede ver a continuación.
Echemos un vistazo a los puntos:
[1] "El trabajo se realizó con mucho cuidado"
No veo dónde, ni un argumento, ya que no hay ejemplos.
[2] "Parece que el desarrollo persiguió los objetivos de" funciona "e ignoró" cómo funciona ".
No es un argumento, no hay ejemplos.
[3] "Según nuestros requisitos para los niveles de candidatos, la tarea completada apenas llega a la mitad".
Cuales son los requisitos? Donde estan
[4] “Esperamos que los filtros no estén codificados y se adapten a los datos. Si va a aviasales, puede ver que los boletos se muestran inmediatamente cuando aparece la primera entrega, y no esperamos que todos carguen ".
Este requisito no estaba en la tarea adjunta. Y la aplicación Aviasales en sí misma, en mi opinión, no tiene una interfaz de referencia, y saltar tickets no es la mejor solución.
[5] “¿Por qué filter.service sabe acerca del enrutador y la ventana? No debe controlar el estado de la aplicación y tener tales dependencias en absoluto ”.
Porque los servicios se crean para controlar el estado de toda la aplicación o el módulo donde existen. Aquí el autor sugiere claramente escribir toda la lógica en los componentes.
[6] “Trabajadores web. ¿Cuál es el beneficio? En este caso, se gasta mucho tiempo en operaciones asincrónicas, y la carga guardada en el hilo principal se gasta en serializar / deserializar objetos (y objetos observables). Si hablamos de optimizaciones, valió la pena comenzar no con la eliminación en el trabajador web, sino en solucionar los problemas en el hilo principal ".
¿Cómo puedo manejar el procesamiento de grandes cantidades de datos en el hilo principal y al mismo tiempo sin retrasos en la interfaz? Estaré muy interesado en saber si alguien tiene un ejemplo, luego escriba los comentarios. Al parecer me estoy perdiendo algo.
[7] "No tiene sentido agregar rxjs al proyecto solo para implementar el reintento y la carga secuencial".
¿Por qué no tiene sentido? Puede importar funciones estrictamente necesarias en RxJS; si los paquetes y las funciones de árbol no funcionan correctamente, esto no aumentará el tamaño de la aplicación.
[8] “El proyecto no se puede escalar y mantener. Construcciones como (ticket.segments || [{}, {}]).map((ticket) => ...)
muy engorrosas ".
Veamos los criterios de escala y soporte: accesibilidad (los servicios resuelven este problema), los riesgos ( ticket.segments || [{}, {}]
son solo un ejemplo de cómo tratar casos si la entrada no contiene datos. Un ejemplo es malo, pero el enfoque de estructura anulable al menos, pero trato de cumplir), código limpio (bueno, al menos sé lo que es :), aunque traté de escribir todo como debería). Parece que todo está capturado, nuevamente no es una discusión.
[9] “Tengo la impresión de que no hay absolutamente ninguna comprensión de cómo funciona React bajo el capó. Hay muchos errores críticos al trabajar con accesorios para componentes que tienen un efecto muy negativo en el rendimiento. Los mecanismos de optimización de reacción son ignorados ".
No puedo entender dónde están estos problemas descritos. ¿Qué tipo de mecanismos?
[10] "Crear funciones de controlador dentro de render".
No tengo ninguna función de controlador en render, ¿alguien entiende lo que está escrito aquí? Incluso transferí el procesamiento de formato a Web Worker
[11] “Crear un nuevo objeto vacío y transferirlo al ticket. ticket-list-loading.jsx:10
o Ticket.tsx:24
"
Aquí no hay nada crítico, excepto por mi pereza para sacar por separado el componente de boleto de carga. Pasar un objeto vacío no viola ningún principio de programación, excepto que aquí fue necesario hacerlo a través de ticket = ticket || {};
ticket = ticket || {};
pero esto se debe únicamente al hecho de que el tiempo de desarrollo se limitó a un día y tomaría más tiempo solucionar todos los defectos menores.
[12] "Índices de matriz como claves en la lista de tickets"
Hay más bien una pregunta de por qué api no devuelve elementos con id. Por lo tanto, al recibir datos del servidor, necesitaría generar claves únicas para cada elemento, lo que no hice como parte de la tarea de prueba, ya que incluso en un proyecto real este es un enfoque dudoso.
Y finalmente, la conclusión: "En general, React no funcionó (
Total: para el nivel medio, esperamos que no haya problemas críticos con la reacción, pero hay muchos de ellos en el trabajo realizado ”.
Ya no hay comentarios ...
Gracias si lees hasta el final. Tengo una opinión muy negativa sobre Aviasales, así que publico todo aquí para que pueda evaluar si debe contactarlos o no.
Texto completo del mensaje:
El trabajo se realiza con mucho cuidado. Parece que durante el desarrollo los objetivos fueron "funciona", y "cómo funciona" fue ignorado. Según nuestros requisitos para los niveles de candidatos, la tarea completada apenas llega a la mitad.
Rendimiento y estructura:
Esperamos que los filtros no estén codificados y se adapten a los datos. Si va a aviasales, puede ver que los boletos se muestran inmediatamente cuando aparece la primera entrega, y no esperamos que todos carguen.
Además, más puntos técnicos.
- ¿
filter.service
qué filter.service
sabe sobre enrutador y ventana? No debe controlar el estado de la aplicación y tener tales dependencias en absoluto. - Trabajadores web. ¿Cuál es el beneficio? En este caso, se gasta mucho tiempo en operaciones asincrónicas, y la carga guardada en el hilo principal se gasta en serializar / deserializar objetos (y objetos observables). Si hablamos de optimizaciones, valió la pena comenzar no con la eliminación en el trabajador web, sino solucionando los problemas en el hilo principal.
- No tiene sentido agregar rxjs al proyecto solo para implementar el reintento y la carga secuencial.
- El proyecto no se puede escalar y mantener. Las construcciones como (
ticket.segments || [{}, {}]).map((ticket) => ticket
) son muy engorrosas.
Reaccionar:
Tengo la impresión de que no hay absolutamente ninguna comprensión de cómo funciona React bajo el capó. Hay muchos errores críticos al trabajar con accesorios para componentes que tienen un efecto muy negativo en el rendimiento. Los mecanismos de optimización de reacción son ignorados. Brevemente sobre los problemas: - Crear funciones de controlador dentro de render.
- Cree un nuevo objeto vacío y transfiéralo al ticket.
ticket-list-loading.jsx:10
o Ticket.tsx:24
. - Matriz de índices como claves en una lista de tickets.
En general, React no funcionó :(
Total: para el nivel medio, esperamos que con la reacción no haya problemas críticos, pero hay muchos de ellos en el trabajo realizado.