Duda JAVA - API REST + springboot

JuAn4k4

#27 El móvil... Que escribe lo que le da la gana

1
TitoBurns

Yo hice una prueba parecida y me pedían lo mismo, básicamente que ignorase la parte de BBDD, así que tire por h2 memory, así que creo que vas por buen camino.

Sobre lo de que sea concurrente no te puedo ayudar mucho porque no domino ese tema de Java, haria caso y me miraria lo que comenta #11.

A mi por suerte me pidieron una API REST para un banco simulando transacciones, así que tire con @Transactional de Spring que eso si que lo dominaba más.

0nLy

#30 Si, yo lo entiendo así tambien. Al final dudé entre dejarlo con h2 o ConcurrentHashMap y decidí dejar el map para que se vea que utilizo streams, filtros etc

A ver que tal va

Traber

#13 #17 No hablo del rendimiento de la colección sino del de la api, a lo mejor lo he explicado mal xD.

0nLy

Hola! Vengo a buscar sabiduría otra vez a vosotros.

Bueno, la prueba esta era para acceder a un trabajo en un puesto de programador java, después de una semana me han respondido que les ha gustado la prueba que hice y tengo "pronto" (no sé cuando todavía) una entrevista técnica con ellos, así que muchas gracias a todos por ayudarme! ^^

El caso es que me estoy preparando la entrevista pero tengo un par de dudas que me gustaría que alguien me explicara, ya que en la prueba hice algunas cosas que nunca he tocado y fué un poco busqueda rápida de google porque no tenía tiempo para más:

1) Hice un endpoint create "normal" y un create asíncrono, cual es la diferencia/ventajas entre uno y otro?

spoiler

2) Nunca he trabajado con ConcurrentHashMaps, me pidieron que los datos se almacenaran en memoria así que buscando opciones y con la ayuda de la pagina anterior del hilo me decidí a usar eso, pero todavía no sé muy bien las ventajas/diferencias entre usar eso o un hashmap normal (se debatió un poco en la pagina anterior) o una base de datos corriente (Entiendo que la ventaja sobre la bbdd es que para este tipo de pruebas es simplemente más rapido y se puede ejecutar sin necesidad de la bbdd).

spoiler

3) Por qué la capa de servicio es una buena práctica dividirla en la interfaz y en la impl? Esta pregunta es más genérica y puede parecer una chorrada pero no sé muy bien por qué y siempre lo veo así, sé como funciona, pero no sé muy bien la razón de por qué se hace.

De momento esas dudas me han surgido leyendome el código, perdón por el tocho :$

Gracias otra vez! Un saludo

1 respuesta
MTX_Anubis

#35

#350nLy:

1) Hice un endpoint create "normal" y un create asíncrono, cual es la diferencia/ventajas entre uno y otro?

Cuando no sepas algo lo mejor es ir a la documentación y leerlo:

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#supplyAsync-java.util.function.Supplier-

Returns a new CompletableFuture that is asynchronously completed by a task running in the ForkJoinPool.commonPool() with the value obtained by calling the given Supplier.

La diferencia entre los dos es que la primera bloquea el hilo hasta que se resuelva la tarea, la segunda te manda la tarea a un forkjoin (un tipo de pool de threads) y se resuelve en paralelo en otro hilo.

Para que sirve el @Async y hacer a su vez el CompletableFuture? Pues juraría que para nada porque @Async envía la invocación a otro pool de hilos para ejecutarla.

Desde el punto de vista de un cliente: Con el primer método, para recibir la respuesta, esperaría a que se creara el producto para devolver el 200. Con la invocación Async lo devolvería al momento, pudiendo fallar la creación del producto, pero el cliente siempre recibiría un 200.

Esto es una suposición porque tampoco sé que hace Spring con los Futuros. Algunos frameworks devuelve el 200 cuando se terminan y haciendolo async consiguen que no se bloqueen el hilo que despacha las peticiones ni tienen que crear otro hilo por cada petición. Si quieres algo más de información sobre esto te lo explico mejor cuando pueda.

#350nLy:

2) Nunca he trabajado con ConcurrentHashMaps, me pidieron que los datos se almacenaran en memoria así que buscando opciones y con la ayuda de la pagina anterior del hilo me decidí a usar eso, pero todavía no sé muy bien las ventajas/diferencias entre usar eso o un hashmap normal (se debatió un poco en la pagina anterior) o una base de datos corriente (Entiendo que la ventaja sobre la bbdd es que para este tipo de pruebas es simplemente más rapido y se puede ejecutar sin necesidad de la bbdd).

Sobre esto lo más sencillo y mejor hecho es una BBDD pero bueno. El por qué usar un Concurrent en vez de un Hashmap normal es por lo siguiente:
Funcionamiento normal

1 - Haces un put
2 - El hashMap calcula en que posición de la tabla hay que guardarlo. Para esto mapea el hashCode que devuelve la Key a un index y cada posición puede contener 1 o varios valores ya que distintas Keys pueden llegar a mapearse al mismo index con lo cual en cada index habrá una lista de nodos
3 - Aquí lo inserta en la lista y hace un resize de la tabla si es necesario.

Qué ocurre cuando haces peticiones de forma concurrente que modifiquen esa tabla o las listas asociadas? Una explicación un poco grosso modo.

Al insertar 2 a la vez en el mismo Index estás modificando concurrentemente la lista asociada a ese Index:

Imaginate que inserto dos valores D y E y la key de ambos (aun siendo distintas) se mapean al index 10 y en el index 10 tengo esto:
tabla[10] = > Noda(A) -> Nodo(B) -> Nodo(C)

De forma paralela, en ambos llego al nodo C y le voy a meter el siguiente que sería en un caso D y en el otro E. La ejecución ocurre en este orden:
Hilo 1: saco nodo C
Hilo 2: saco nodo C
Hilo 2: le inserto D
Hilo 1: le inserto E

Resultado?

tabla[10] = > Noda(A) -> Nodo(B) -> Nodo(C) -> Nodo(E)

Con el resize de la tabla ocurre algo parecido.

#350nLy:

3) Por qué la capa de servicio es una buena práctica dividirla en la interfaz y en la impl? Esta pregunta es más genérica y puede parecer una chorrada pero no sé muy bien por qué y siempre lo veo así, sé como funciona, pero no sé muy bien la razón de por qué se hace.

Esto es por favorecer la separación de contratos con las implementaciones para poder testear. Imagina que quieres testear que los controladores devuelve correctamente el status code en las respuestas dependiendo de los errores que da el servicio. Pues puedes montarte implementaciones fake del servicio que devuelvan las excepciones que quieras. Podrías hacer 2 implementaciones para un mismo servicio (una que genere el logging además o envíe eventos de las acciones a otro lado) y cosas así.

También te digo que es una práctica arrastrada de hace 20 años lo menos, actualmente con los inyectores de dependencias que hay te inyectan mocks y no hace falta andar con interfaces para todo y menos en la capa de servicios (que va a ser raro que tengas que tener varias implementaciones si no es para testing).

Y vamos esa pregunta que te haces se la llevan haciendo desde hace 10 años:

https://www.adam-bien.com/roller/abien/entry/service_s_new_serviceimpl_why

1 1 respuesta
0nLy

#36 Muchas Gracias, así da gusto! :)

Alguien me podría pasar un ejemplo de un readme de un proyecto simple? Me han chivado que preguntan por él en la entrevista pero yo no lo hice y aún estoy a tiempo.

Y otra pregunta, los archivos maven que se autogeneran en la raíz del proyecto (mvnw, mvnw.cmd), se podrían eliminar o los dejo?

1 respuesta
Lecherito

#37 Dejalos, es lo que necesitas para ejecutar las acciones de maven (a no ser que lo instales en tu pc manualmente), es un simple wrapper para descargarse maven y usarlo sin que lo tengas que instalar tu