que es una entrevista técnica - parte 2

D

¿Qué es una entrevista técnica? - Parte 2

Venimos de la primera parte donde comentamos unos rasgos principales de una entrevista técnica. Recordad que en esta serie nos estamos centrando en las entrevistas técnicas que intentan ser proyectos “realistas” de desarrollo. No estamos hablando de leetcodes o algoritmia, sino de tareas que normalmente realizamos en casa y entregamos. Se suele hacer pair-programming y comentar la solución.

Analizando una técnica

Muchas veces hay que ponerse en la piel del entrevistador para comprender qué está buscando. Es lo que os voy a exponer en esta segunda parte. Vamos a analizar un pequeño trozo de código, que se puede realizar en un par de horas, y lo evaluaremos basándonos en la parte 1.

¿Qué tenemos que mirar en una prueba?

Paso 1: Funciona

Para verificar esto estaría bien tener unos tests. Una Github Action que haga Build y Test es una manera rápida para mí de ver que has hecho el esfuerzo en hacer mi trabajo fácil. Depende del proyecto, la manera de ejecutarlo en local debe ser obvia. Voy a hacer un git clone, y me gustaría hacer un “run” o “test” mediante Maven, Gradle, Go, Cargo, NPM… Imagina que soy tu compañero y te tengo que hacer una Code Review; no debería llevarme más de un minuto.

Paso 2: Resuelve el ejercicio

Una vez haya visto que todo tu código se ejecuta, miraré los tests y comprobaré que estás verificando la funcionalidad y los requerimientos que te he pedido. Seguramente aún no haya visto ni el código ni me importa en qué lenguaje o stack está hecho tu ejercicio. Miraré lo que los tests hacen porque el objetivo de los tests es el siguiente:

  • Primero, documentar el código para tus compañeros, es decir, podría ser yo que te he pedido un MVP de una funcionalidad.
  • Segundo, comprobar que las funcionalidades y requerimientos que has implementado funcionan.
  • Tercero, realizar un contrato de los requerimientos. Llamamos a esto tests de integración o funcionales.

Y os puede sorprender, pero la gran mayoría de gente no pasa el Paso 1, y muchísimos fallan en el Paso 2. Si he revisado 100 pruebas, os aseguro que en 97 de ellas no he mirado código más allá de los tests ni me ha hecho falta.

Idealmente, me gustaría tener algún tipo de test de integración o e2e. Según la prueba, pueden ser difíciles, pues ponme en el README 3 o 4 comandos que pueda copiar y ejecutar en mi terminal para comprobar que tu solución resuelve el ejercicio. No pasa nada. Si puedes hacerme un docker-compose que me levante todo y solo tenga que ejecutar un bash, genial. Mucho mejor si me lo pones en una Github Action. Como podéis observar, gran parte del trabajo de ingeniería se basa en hacer la vida fácil a nuestros compañeros.

No quiero suspenderte, entiendo que quizás no has tenido diez mil horas y no has podido automatizarme todo... Te pido y valoro que hayas hecho el esfuerzo de comprobar que las cosas funcionaran fácilmente para mi, gracias.

Paso 3: Tu solución

Si cumples con los requerimientos anteriores, por primera vez me miraré tu código para ver cómo lo has resuelto. Hay gente que hace barbaridades para que los tests pasen… y eso no es resolver el ejercicio. Espero no llorar demasiado. Fijaos que en el último paso es donde tú has pasado la mayor parte del tiempo. En cambio, yo como evaluador pasaré unos 15 minutos… si llego. Y si toco algo de tu código quizás sea para añadir algún test que creo que te puede fallar. Fijaos que en optimizar el último paso, la revisión del código, es donde la gente se pasa la mayor parte del tiempo haciendo sobreingeniería y picando auténticas locuras que han leído en un libro con la portada azul de DDD, o un libro sobre lambdas de FP (Programación Funcional) con la portada roja. No me vas a impresionar con un código que seguramente no voy a mirar. Me vas a impresionar si tu código es fácil de entender y resuelve lo que te he pedido.

Fijaos también que si la prueba ha sido bien diseñada y tú has hecho unos buenos tests, realmente me da bastante igual tu código. Se pueden dar dos casos:

  • Si es una posición de junior y funciona, ya has aprobado.
  • Si es una posición que requiere más capacidad técnica, la prueba tendrá condiciones (como usar HTTPS y autenticación, por ejemplo) que habrás tenido que testear. Si no las has hecho, no pasarás la prueba. Si las has hecho, leer el punto anterior.

Así que si, si hay algo que no has testeado por falta de tiempo y esta implementado y funciona documentadlo. Y si, si me tienes que poner un e2e que sea correr tu programa y hacer un curl pónmelo en el README. No pasa nada, no restara puntos.

Paso 4: Opcional

Entonces, para qué cojones voy a mirar tu código? Aquí es donde desarrollé en la parte 1 que pasado un nivel de capacidad técnica básico, se buscan otras características en una prueba. No entraremos en detalle.

Cómo preparar una prueba

He pensado que una FAQ puede ser la siguiente cuestión: Si te doy tantos detalles de lo que quiero y cómo lo voy a evaluar, la prueba no será muy fácil? Si solo miras que funcione y los tests, no pasará la prueba mucha gente? Creo que cualquiera que se ha dedicado a revisar pruebas o hacer entrevistas os puede decir que os equivocáis. De hecho, la gente suele ser muy permisiva y candidatos que no deberían pasar la primera fase suelen llegar a fases finales… una pérdida de tiempo para todos.

Como ya sabemos, toda entrevista y prueba funciona en DOS direcciones:

  • El nivel de dificultad se calibra con los requerimientos.
  • El nivel de los candidatos se calibra con el salario ofrecido.

Conclusión

Ponerse en los pies del entrevistador es muy importante antes de realizar una prueba. La persona que nos está entrevistando es nuestro futuro compañero. Y así es como se debe pensar durante toda entrevista con cualquier persona que hables. Queremos trabajar con esa persona? Es esa persona capaz? Como hago la evaluación por parte de mi futuro compañero fácil? Si no tienes empatía, no tienes modales, te suda el tiempo del entrevistador… tampoco te vamos a querer en nuestro equipo. Y lo mismo podemos decir, si el entrevistador es un gandul. No quieres trabajar ahí.

Si no entrevistáis aún a nadie para practicar porque no forma parte de vuestro rol como ingeniero en vuestras empresas, os recomiendo evaluar código de la manera que os explico arriba como ejercicio un par de veces y realizar unas cuantas pruebas.

Para ello, qué mejor que irnos a la “crème de la crème” del desarrollo de software hispano? Empezaremos con nuestros amigos de CodelyTV. He elegido uno de sus proyectos en Java que utilizan como ejemplo de super buenas practicas para sus alumnos. Aquí tenéis el código en Github: CodelyTV/java-ddd-example

Lo vemos en #2

2
D

Analizando CodelyTV/java-ddd-example

Vamos a seguir los pasos que he mencionado uno a uno que debéis aplicar para evaluar un proyecto, ejercicio, prueba de software.

De esta manera, entenderemos perfectamente que debemos nosotros implementar en nuestras pruebas.


Paso 1: Funciona

Pues me llega este código de nuestros amigos el ricitos y el calvito de Codely. En este caso entiendo que es una especie de proyecto Backend, escrito en Java, usando Gradle, que implementa un servicio sobre cursos como los que ellos proporcionan.

Genial, un CRUD de toda la vida. Una prueba que cualquier junior debe saber resolver, en mi opinión en cualquier lenguaje de programación, en un par de horitas.

Requerimientos

Voy a suponer que el enunciado es el siguiente: hazme un CRUD, para gestionar mi software de cursos online. Y tenemos una lista de endpoints y detalles a implementar. Y tenemos como requerimiento utilizar una base de datos de nuestro agrado. Creo que todo el mundo coincidirá, que esta scope de prueba, es accesible. Y todo el mundo coincidirá en que como prueba de backend, puede estar bien.

Funciona o no funciona?

Vayamos directos al grano. Veo un GitHub Action (workflow) que esta pasando: https://github.com/CodelyTV/java-ddd-example/blob/main/.github/workflows/ci.yml
https://github.com/CodelyTV/java-ddd-example/blob/main/Makefile

Así que a priori tiene buena pinta.

Me pongo en el papel de compañero, vamos a revisar este MVP o imaginaros que es una PR muy grande. Me voy a hacer un fork o clonar en mi local. He decidido hacer un fork. Y sorpresa:
https://github.com/vrnvu/java-ddd-example

Lo podeis comprobar vosotros mismos, haced un fork al proyecto, se os ejecutara la CI y os fallaran los tests.

Failed to map supported failure 'org.opentest4j.AssertionFailedError: expected: <Optional[tv.codely.mooc.courses_counter.domain.CoursesCounter@1ad7f6df]> but was: <Optional[tv.codely.mooc.courses_counter.domain.CoursesCounter@b2b17e14]>' with mapper 'org.gradle.api.internal.tasks.testing.failure.mappers.OpenTestAssertionFailedMapper@3746766b': Cannot invoke "Object.getClass()" because "expectedValue" is null
2024-07-22T19:56:47.792Z  INFO 397 --- [ents_consumer-2] o.s.a.r.l.SimpleMessageListenerContainer : Waiting for workers to finish.
2024-07-22T19:56:48.422Z  INFO 397 --- [ents_consumer-2] o.s.a.r.l.SimpleMessageListenerContainer : Successfully waited for workers to finish.

Task :mooc:test FAILED

MySqlCoursesCounterRepositoryShould > return_an_existing_courses_counter() FAILED
    org.opentest4j.AssertionFailedError at MySqlCoursesCounterRepositoryShould.java:21

Paso: No hire

Que hago ahora que me llega una prueba que no funciona? No hire.

Yo soy buena gente, y a veces dedico 5-10 minutos si tengo tiempo a ver porque le ha petado. Quizás es una tontería que se ha dejado un push al final o tiene un flaky test... No hire.

Os llega un proyecto, si lo veis por dentro lleno de sobre ingeniería, ademas pretende ser un tutorial de buenas practicas, y en el mejor de los casos, tiene un flaky tests al arrancar. No hire.

Y lo voy a dejar aquí. Se que muchos quieren verme analizar todo lo bien o mal que hace ese proyecto. Porque sois unos morbosos. Pero es que no ha pasado ni el Paso 1: Funcionar.

Conclusión

Como lección, antes de enviar asegúrate que no tienes flaky tests. Ejecuta los tests durante horas si hace falta por favor. Puedes tener un re-trigger de tu Build en master durante un día antes de mandar... Asegurate que esta bien. Haz un fork como yo he hecho de tu practica...

Imaginate que te has estado diez horas haciendo ese super proyectazo con DDD y mil historias, le he dedicado 5 minutos a revisarlo porque no funciona tío. Me sabe mal, pero es que esto no es profesional.

Paso numero 1, siempre, el código FUNCIONA.

Creo que este es un gran ejemplo de lo que he explicado en la parte 1 y en esta parte 2. Porque la verdad, no era mi intención que el código no pasase el paso 1 y tenia verdaderamente intención de analizarlo un poquito. Pero sorpresa. No funcionaba jaja. Código con todas las buenas practicas y sobré-ingeniería del mundo, todo lo que tu quieras. Pero eh, falla el Build en master. No hire.

1
Kaledros

Además de eso, hay cosas que no entiendo. Esto:

Execute some Gradle lifecycle tasks in order to check everything is OK:

  • Create the project JAR: make build
  • Run the tests and plugins verification tasks: make test
  • Start developing!

¿Para qué tengo que buildear en local via comando si tengo un workflow en la carpeta .github y por lo tanto lo puedo lanzar así? Es más, ¿por qué tengo que lanzar los tests por separado si un simple gradle build ya los lanza? ¿No saben como funciona Gradle?

1 respuesta
HeXaN

#3 Pues les respondes justamente eso y ven que sabes.

Hurtiek

Entiendo que muchas veces, como has comentado, las pruebas técnicas las escriben personas que no son técnicas, por lo que si te diesen un par de horas para todo eso que comentas y ves que no te da para todo, en qué te centras? Entiendo que en el desarrollo en si y el tema de tests, GitHub Actions, etc queda descartado.

2 respuestas
Kaledros

#5 Te centras en entregar valor. Una funcionalidad completa es mejor que cinco sin acabar. Siempre puedes comentarlo en la review de la prueba y explicar cómo lo hubieses hecho y demás.

1
pantocreitor

Es un proyecto de buenas prácticas, te enseñan lo que no son buenas prácticas no? xD

D

#5 No entiendo exactamente a que te refieres.

Si no puedes hacer toda la prueba:

  • Si puede ser que la prueba sea excesiva... o consideres q no pagan suficiente para realizarla
  • Si tambien puede ser que no tengas nivel suficiente

En que te centras? https://www.mediavida.com/foro/dev/entrevista-tecnica-parte-1-713050

#5Hurtiek:

Entiendo que en el desarrollo en si y el tema de tests, GitHub Actions, etc queda descartado.

No entiendo bien, esa frase se lee extraño. Si dices que no hay que hacer tests ni GitHub Actions Vuelvete a leer los hilos porque si no me demuestras que tu codigo funciona, ni me lo voy a mirar. Lit no has entendido nada o lo has entendido del revés jaja

Honestamente, si no me sabes entregar un codigo testeado y con una action que son 2 lineas y te genera chatGPT, no estas ni a nivel de junior.

Todo codigo que me escribas debe funcionar y debes demostrar de alguna manera que funciona.

laZAr0

Gracias por el aporte @desu.

Para los que no tenemos ni idea de desarrollo web, ¿qué bibliografía/tutorial/proyecto podéis recomendar seguir para tener una primera toma de contacto y hacer un ejercicio con lo que pides en #1? Es decir desarrollar una API e implementar y testear las operaciones CRUD (para el workflow de GitHub Actions entiendo que me puedo remitir a la documentación oficial, pero eso vendrá después). Llevo días dándole vueltas a hacer una pequeña web como proyecto personal y esto supongo que es la base del proyecto, a groso modo.

1 respuesta
D

#9 Haz una TODO list.

Empieza con el MVP mínimo que se te ocurra y el objetivo es terminarlo.

  • Crear una tarea
  • Completar una tarea
  • Ver tareas pendientes
  • Ver tareas completadas

Y abrete un diaro para compartir para que la gente te ayude. Estoy seguro que los proyectos fáciles como esto mucha gente aportara.

Primera version:

  • Los 4 features anteriores
  • Usa de base de datos un HashMap/Diccionario
  • Todo testedo con test unitarios e integración
  • Meterlo en Github y un workflow para build y test.

La gran mayoría de programadores piensa en proyectos grandes y los empieza pero nunca los termina.

Si eres capaz de empezar algo y hacerlo funcional, es decir, terminar una primera versión. Ya estarás en buen camino.

Creo que con esto, según tu nivel, ya tienes para muchas horas de aprendizaje.

Una vez termines la primera versión. Puedes añadir otros features o cosas que se te ocurren hasta que te aburras del proyecto:

  • Editar tareas.
  • Tener multiples listas de sub-tareas. TODO/WIP/DONE
  • Mover las tareas de una lista a otra lista.
  • Añadir una fecha a las tareas y prioridades
  • Poder ordenar por fechas y prioridades
  • Usuarios, autenticación, sesiones... etc
  • Añadir alguna base de datos y docker

Por ejemplo si miras mis últimos proyectos que he compartido y tienen hilos en el subforo:

El famoso bittorrent que ha mucha gente le da miedo. Pues el procedimiento es el mismo que en cualquier proyecto. Vas paso a paso haciendo cosas funcionales, las testeas, y poco a poco construyes sobre la base. Exactamente que un CRUD de una todo List.

Y ya esta, ponte un objetivo muy asumible, es mejor que sea fácil y simple que algo difícil y complejo y terminalo.

4
y34hl0ve

Gracias por el curro @desu !!

Tío, estas son las cosas que me matan (soy un fpero pringado)

Yo me hago mi CRUD ahí de puta madre, te hago lo que gustes con la API, pero... ¿Qué coño es Github Actions? ¿Cómo que gradle build? si yo solo he complicado con javac... ¿Qué es un workflow? ¿Por qué hay 30000 tutoriales de lenguajes de programación y parece que nadie enseña estas cosas que parece que son básicas? y lo mas importante ¿Por donde empiezo para aprender todo eso? xD

2 respuestas
GlitterSpark

#11 se aprende trabajando, o contribuyendo en OS.

1 1 respuesta
D

#12 en la universidad te lo enseñan y se dan varias asignaturas.

hoy en dia trabajar en equipo es igual de importante que saber programar.

#11 Pues hombre, te faltan herramientas elementales.

Aprende sobre Maven y Gradle, como se usan para hacer build, gestionar dependencias, correr tests... Es básico. Lo importante es gestionar dependencias, build, test y run de tu codigo. No hay mas misterio ni hace falta mas para la gran mayoria de codigo.

Y lo mismo lo encontrarias en otros ecosistemas, en algunos forma parte del tooling oficial como Go o Rust, en otros como Python o Javascript/Node, tendrías alternativas como Poetry y Conda para python. Npm, Yarn, Deno para javascript por ejemplo.

Aprender a usarlo... como digo, no hace falta un gran nivel tecnico de entendimiento sino nivel de usuario. Pues son un par de dias de toquetear... No mucho mas.

CI/CD pues para correr procesos que todo el equipo necesite, como los tests y desplegar el código de manera automática.
https://github.com/features/actions
https://docs.gitlab.com/ee/ci/

Aprender a poner las 3-4 pipelines/workflows básicos de nuevo, son un par de dias de toquetear. No tiene mucho misterio. Si sabes lo que es un script... pues lo estas corriendo en una maquina virtual... no tiene ningún secreto.

Como empiezas? Pues empieza añadiendo maven o gradle a tu proyecto java para gestionar las dependencias, hacer el build y test.
Y una vez tienes un entorno funcional prueba a subirlo a Github y Gitlab y ejecutar tu build y test en estas paginas.

1 1 respuesta
y34hl0ve

#13 Solo había tocado Maven y exclusivamente para descargar alguna dependencia, no había pasado de ahí y soy tan subnormal que no había caído que es como npm...

Justo me estaba viendo un vídeo de tu querido amigo Midu donde explica el CI/CD con Github Actions, ya lo tengo todo muchísimo mas claro.

Muchas gracias!

D

Iba a hacer un hilo pero bueno, siguiendo el feedback que me han dado aprovechare este hilo.

He entregado una prueba.

Paso 1: funciona?

Primero un README con explicación:

En el README esta bien comentar lo que has hecho y lo que no, en este pongo unas referencias de papers que he usado o para comentar en el futuro. Comento lo que he implementado y lo que no porque me daba pereza... En este caso por ejemplo mi api no devuelve 400, 404 ni demas validaciones... devuelve todo 500 y a pastar. Tampoco tengo HTTPS (no lo pedia). Me he centrado en resolver lo que me han pedido. Tambien me dedican que los objetId debían ser de una manera concreta, NO LO HE VALIDADO TAMPOCO, que mas da? No veo en que ese detalle influya en la prueba, creo que esta relacionado con el algoritmo de "partitioning" que he usado o era una pista sobre ello.

La estructura del codigo un poquito ordenada y siguiendo el estándar habitual:

Tres GitHub Actions / workflows, muy simples, para test, Lint y los de integracion:

Todas pasan, no soy Codely o Miudev.

Ahora, si tu eres el entrevistador pues te haces un clone mismo y miras si de verdad esas Action funcionan. Yo antes de entregar le he hecho re-run a todo.

Asi que PASO 1 completado. MI codigo funciona.

Paso 2: Resuelve el ejercicio?

Ahora mi codigo resuelve el ejercicio? Para ello hay que mirar los tests. Y ya os he comentado que he tomado las libertades que he creido.


Mi test de integracion es muy simple, casi todos mis tests los ha generado ChatGPT... Y no tengo problema en comentarlo en la entrevista y decirlo. Fijaros que lo que estoy testeando es que subo un archivo y me lo descargo. Para esta prueba, este mini test pues ya esta bien, podria hacerlo mas complejo y hacer multiples PUT? podria, pero chatgpt no me lo ha hecho, y la verdad, me da pereza. No creo que sea muy relevante. Lo que importa es que el test de integración existe y se corre en CI.

Los test unitarios son mas completos, y utilizo unos mock para comprobar que el codigo ejecuta el path que quiero. Son muy simples, si quiera hacer test de integracion debería meter test containers por ejemplo. No me apetece.

Asi que paso 2, resuelve lo que tiene que resolver? Si.

Conclusiones Paso 1 y Paso 2

Como podeis intuir por lo que os comento, porque no puedo compartir el código y solo enseñare lo minimo. Mi codigo no es nada del otro mundo hasta aqui. Es codigo simple, no es el mas eficiente ni óptimo, los status code y cosas de HTTP me los he fumado.

Entonces, porque he completado el paso 1 y paso 2? Porque he escrito buenos tests tanto de integracion como unitarios, que demuestran, que he resuelto la prueba. La prueba me pedia 2 cosas solo, bajo un par de restricciones. Pero la prueba consistía en hacer UN PUT y UN GET y que funcionase. Y eso esta resuelto, y de manera fácil y rápida, lo puede comprobar el evaluador.

De hecho he escrito tan poco codigo que hasta hay alguna cosa como el objectId que he comentado que me lo he fumado. Porque se al 100% que solo era una pista para la gente con menos experiencia. Asi que, he entregado una prueba, relajado de que esta correcto, usando ChatGPT para los tests, y dejándome cosas. Si. Y estoy convencido de que voy a pasar este proceso sin problema y os lo comparto. Para que veáis lo que realmente importa y lo que no.

Paso 3: Mi solución en si

Llegados a este punto yo estoy muy convencido que estoy fuerte. Pero el entrevistador tambien tiene que pensar: este tio pilota. En lugar de: este tio no se ha leído ni el enunciado. Es un riesgo que no me importa tomar.

Para empezar he utilizado todo tecnología e ideas de implementación que estan en State Of Art del problema. Lo he puesto en el README. Y he referenciado las posibles preguntas que me harán en el futuro, para dejar claro que no hay detalle que no pueda implementar en la siguiente entrevista si quieren.

Segundo en mi código he utilizado: métricas y logs, he utilizado circuit breakers para llamas externas, he utilizado un par de técnicas avanzadas de sistemas distribuidos como virtual nodos, el hash que he utilizado también es un poco especial por ser super eficiente. Así que si, he programado 200 lineas quizás 300 lineas de código. Y en estas me he centrado en dejar de talles de "calidad" que cualquier otro ingeniero vera que se lo que estoy haciendo.

Veamos unos ejemplos:

  • Circuit breaker por METODO y NODO. Con métricas y logs especificos. Esto lo que implica es tener control absoluto en todas las peticiones al servicio externo que uso. Si por ejemplo tenemos dos regiones EU y US, y peta 1 región, no afectara a todo mi servicio. Si solo peta una AZ, tampoco afectara a toda la región. Ademas, puedo tener el CB a nivel de tenanat/usuario... Cuando el circuito cambia de estado como digo logeo y meto métricas. En fin, esta perfecto, porque de hecho yo he colaborado en esto en el ecosistema Go... Asi que estoy tranquilo en este sentido jaja.
  • Os voy a enseñar un turquino de parsing y una MALA PRACTICA típica de Tiktoker. Pero ahi va. Usar SPLITS es una MALA PRACTICA. String.Split() es una mala practica!!!! Siiiii. tiene sus casos de uso, no soy un tiktoker, pero la mayoria de gente lo usa mal. Aqui teneis un detallito de calidad:

El punto clave es que un split devuelve un silce, array, vector. Y en una variable de entorno "VAR_A=" es un input valido, de hecho podríamos tener mediante chars especiales (si no me equivoco), "VAR_A=fo=bo" o similares... Si hacemos un split en el = tendremos que comprovar el tamaño del array y luego el contenido... En conclusión, como se Rust y cosas de bajo nivel, y se que se hace con estos métodos pues lo he hecho bien.

Y aqui he sido un poco cabroncete. Me he ido al GitHub publico de la empresa donde estoy aplicando y he buscado casos de uso donde hagan split... Y he visto 2 o 3 sitios como este donde ese codigo esta mal. Asi que en la entrevista. Se lo voy a enseñar.

  • Algo básico, todo el tema de I/O es async obviamente. Cuando subo un fichero a un nodo lo hago en stream/multipart y dejo que la stdlib y el kernel se encarguen de la transmisión y los retries... De nuevo, en esto he trabajado al mas alto nivel y en librerías open source como Reactor, Betty y similares. Tengo los huevos pelados que dicen.

Aqui tambien he sido perro y he mirado otras soluciones de otra gente que estan por GitHub, no lo hacen en streaming todo... hay cosas que leen en memoria. Es decir copias y luego vuelves a copiar al buffer... Puede tener out of Memory, te puede petar una transmisión, ademas que delegas el retry al user space en lugar del kernel... Una puta porqueria vamos.

  • Otro ejemplo que parece tonto si no sabes lo que estas viendo, pero es la diferencia es este filtrado. Mucha gente hace un List() y luego filtra en su proceso. Eso esta mal. Yo aqui que estaba usando el SDK de Docker para pillar unos cointainers según la network, le he pasado un filtro:

Como sabia que esto se puede hacer? Pues he buscado en Github en todos los repositorios del mundo esta string: "containertypes.ListOptions{" y me salían todos los ejemplos de proyectos públicos que hacen este listado.

Sorpresa, NO HAY NADIE EN EL MUNDO, que haga el filtro bien de docker.. al menos en codigo open source. Soy el unico. Pues esto se comenta en la entrevista obviamente. Y de nuevo, los otros entrevistados tambien hicieron mal...

Quizás este List es una tontería, pero lo que esta linea de codigo esta comunicando es que entiendo lo que estoy haciendo y estoy usando el mejor codigo eficiente y optimo para cada situación. Es el equivalente a hacer una query bien optimizada a db vs hacerlo tu en runtime al recibir una respuesta peor... todo suma.

  • luego tema http, no le he metido status code y tal ya lo he dicho. pero si he metido logs y métricas inFlight del numero de peticiones que recebimos. si estoy escribiendo una gateway es importante estas métricas. al final esto es un tema de conversación y es un must en cualquier codigo para producción... de nuevo, soy el unico candidato de todos los que he visto en github ( otros 3 programadores) que ha puesto métricas y logs de calidad.

Conclusion

Bueno como veis en el tocho post, he hecho lo que de verdad importa. Mirando las otras soluciones, si 4 o 5 candidatos han hecho el mismo problema que yo. Todos podemos resolverlo. Pero yo he sido el unico con tests, con tests de integración, con CI en Github, con explicación en el README, con los detalles que comento arriba de circuit breaker, técnicas avanzadas de sistemas distribuidos, métricas, logs... etc. Lo que me he centrado es en resolver el problema, que funcione bien, rápido, eficiente y bastante cerca de ser la solución mas optima de hecho. Y sobretodo, he escrito codigo para el mundo real.

Y como veis no me he esforzado nada en las bobadas que alguien como Codely os venderían. Arquitectura hexagonal? No aporta nada. Hacer DDD o streming de eventos? Complica el codigo... Tu servicio sera mas lento, consumira mas RAM y CPU, tendrá mas puntos de fallo... sera una mierda vamos. Ah, y los tests, con ChatGPT y a otra cosa.

No se, aqui todo el mundo es libre de opinar lo que crea. Vosotros creéis, que yo, por no haber hecho los status code perfectos, no haber validado eso del objectId y dos o tres pijadas mas no debería pasar la prueba? Crees que hacer estas cosas importan para algo para un ingeniero? Ya os digo yo que no. Y si importan y no paso la prueba, viendo el nivel del equipo, tampoco pasa nada.

Cualquier programador te sabe tocar los status code de una respuesta, mappear el error, meter HTTPs... Esto no demuestra nada. Hacer que todo tu servicio funcione completamente en streaming/async y en lugar de consumir 2Gib de memoria y procesar 5k req/s, lo haga en 20MiB y haga 15k req/s. Si importa. De hecho si quiera asegurarme pasar esta prueba al 100%, le habria metido un benchmark y a tomar por culo, os lo recomiendo. Pero no quería complicarme ni dedicar mas tiempo.

Comentadme si quereis screenshots de algo del codigo si no queda claro.

7 1 respuesta
Leagrove

Contenido premium y de calidad, muchas gracias.

D

No se por que en el hilo de No Javascript allowed pareces ser de una forma y aqui de otra, igual te he juzgado mal asi que me disculpo, te agradezco el primero este contenido que a alguien como yo que esta a punto de salir del cascaron del FP (y que todos sabemos como es) le va a venir tremendamente bien, asi que gracias y disculpa si te juzgué mal en el otro hilo que parece hecho para el sarcasmo.

D

Voy a hacer una prueba 4 fun que es la que le propuse a @laZAr0 arriba:

- Crear una tarea
- Completar una tarea
- Ver tareas pendientes
- Ver tareas completadas

Lo voy a hacer con Gradle y Java 21 y Spring básico.

La prueba que yo he compartido obviamente no es un buen ejemplo para los juniors que preguntáis dudas básicas. Porque obviamente no he resuelto la prueba como un junior.

La voy a hace ahora, no me va a llevar mucho rato.. Y luego pues la evaluamos de la misma manera que hemos hecho arriba. Y también os voy a poner varias soluciones para que entendáis mejor los junior que es importante y que no es importante.

Un junior debe centrarse en resolver las cosas dejando menos dudas entre si sabe leer el enunciado o va con la polla fuera. Seguir algunos patrones de diseño y arquitectura, porque no es obvio que sepas programar en 20 lenguajes y 20 paradigmas...

Una prueba para junior vas a pasar mas tiempo en convencionalismos y siguiendo patrones habituales que en una prueba avanzada donde se da por hecho que los sabes.

D

Aqui teneis el ejemplo: https://github.com/vrnvu/java-todo-list

He tardado 1 hora y poco en hacerlo. Creo que el nivel es casi junior. Faltaria algunos detalles pero esta casi terminado. Y yo diría que es casi junior. No creo que hace falta hacer mucho mas, todo lo extra que le metas te va a sumar puntos. Pero es importante que no se te vaya la cabeza metiendo sobre-inginieria que no aporta valor.

Por ejemplo es importante mirar el test coverage:



Lo importante no es tener el 100%, sino que lo importante es que si en algun caso tiras un error, tengas eso en cuenta y lo testéis.

Teneis la pipeline para correr los tests: https://github.com/vrnvu/java-todo-list/blob/main/.github/workflows/build-and-test.yml
Para los que decis que no os enseñan.

Ademas yo uso nix/flox, asi que si teneis flox, os instalara la SDK de java que uso y el gradle exacto para que en local os vaya perfecto.

Podéis usar mi template como base para los que queríais practicar.

Cosas que podríais añadir, algunas mas difíciles que otras:

  • ahora mismo el codigo tiene condiciones de carrera, usar ConcurrentHashMap y testearlo (dificultad facil)
  • cambiar mi inMemory por una H2, ya teneis la dependencia puesta (dificultad fácil)
  • una DB como postgres, RDS, dynamo, mongodb etc... para ello necesitareis tambien docker y docker-compose para tener tests de integracion. (dificultad media)
  • micrometer y log4j y configurarlo (dificultad facil)
  • añadir un prometheus + grafana + opentelemetry para ver los métricas y logs (dificultad medio-difícil)
  • tener mas clases para separar dominio, DTOs, y etnitites. Validaciones y parseos tambien (dificultad fácil)
  • desplegar tu servicio a un AWS/AZURE/GPC (dificultad media)
  • tener gestión de excepciones y mappear las excepciones de tu servicio, repositorios en el controller a errores HTTP (dificultad fácil)
  • tener entornos de spring de dev/pre/pro para configurar la aplicación (dificultad fácil)
  • auth, usuarios, sesiones, jwt, OAuth2 (dificultad media, dificil)
  • ahora mismo no uso tomcat, le he metido netty directamente, que ya es un +1, pero el codigo no es full reactivo xq necesitaría reactor y usar SDK async... hacer tu servicio full async (dificultad muy difícil)

Hablando desde el punto de vista técnico, creo que esto serian las cosas principales.

Para casos de uso de negocio puse atrás ideas.

Espero que os sirva.

Segun ChatGPT:

Interpretación de la Línea de Habilidades

  • JUNIOR: Manejas tareas básicas de concurrencia y persistencia en memoria.

    • Ejemplos: ConcurrentHashMap, H2 en memoria.
  • Intermedio: Puedes manejar bases de datos externas y configurar monitoreo básico.

    • Ejemplos: Docker, Docker-compose, Postgres, Micrometer, Log4j.
  • Avanzado: Configuras y despliegas entornos completos con monitoreo avanzado y separación de responsabilidades.

    • Ejemplos: Prometheus, Grafana, OpenTelemetry, despliegue en AWS/AZURE/GPC, gestión de excepciones, entornos de Spring.
  • Semi-Profesional: Implementas autenticación avanzada y gestionas servicios en la nube de manera eficiente.

    • Ejemplos: JWT, OAuth2, despliegues en plataformas cloud.
  • PROFESIONAL: Desarrollas servicios completamente reactivos y asincrónicos utilizando tecnologías avanzadas.

    • Ejemplos: Netty, SDK async, full reactive programming.

Plan de Mejora Continua

  1. Condiciones de Carrera y ConcurrentHashMap: Prioriza resolver condiciones de carrera y utilizar ConcurrentHashMap para mejorar la concurrencia y estabilidad del sistema.
  2. Migración a H2: Sustituye el almacenamiento en memoria por una base de datos H2 para mejorar la persistencia.
  3. DB Externa y Docker: Introduce una base de datos como Postgres y configura Docker para pruebas de integración, fortaleciendo la infraestructura de la aplicación.
  4. Monitoreo y Logging: Implementa Micrometer y Log4j para el monitoreo básico, luego expande con Prometheus y Grafana.
  5. Separación de Clases y Validaciones: Organiza mejor el código separando el dominio, DTOs y entidades, y agrega validaciones y parseos.
  6. Despliegue en la Nube: Configura despliegues en AWS, Azure o GPC para entornos de producción.
  7. Gestión de Excepciones: Mejora la gestión de errores y asegúrate de mapear excepciones a códigos HTTP adecuados.
  8. Entornos de Spring: Configura múltiples entornos de Spring para facilitar el desarrollo, pruebas y despliegue.
  9. Autenticación y Seguridad: Implementa autenticación robusta con JWT y OAuth2 para asegurar la aplicación.
  10. Servicio Reactivo: Finalmente, transforma el servicio a una arquitectura completamente reactiva utilizando Netty y programación asincrónica avanzada.

See also

You may also enjoy

9 4 respuestas
laZAr0

#19 pero cabrón, desu, produces más contenido del que me da tiempo a leer, y eso que esta semana estoy de baja por paternidad. ¿Cómo puedes ser tan productivo? No sabes cuánto te lo agradezco.

aren-pulid0

#19 muy completo, si señor.

laZAr0

#19 Por cierto, he intentado clonar el repo y tienes un typo en el readme:

git clone https://github.com/vrnvu/java-tood-list

tood en lugar de todo

fatal: repository 'https://github.com/vrnvu/java-tood-list/' not found

NO HIRE

1 respuesta
D

Yo había pensado clonarlo pero no es mejor intentar hacerlo de cero?, bueno igual para mi sería mas aconsejable para aprender sobre todos los pasos, algunos los sé, pero otros no.

Zh3RoX

#22 Puedes clonarlo desde el botón verde del repositorio.

https://github.com/vrnvu/java-todo-list.git

1 1 respuesta
laZAr0

#24 lo sé, lo sé, gracias. Sólo era una coña. :)

D

#19 Gracias por todo el contenido y el conocimiento que no se enseña en los ciclos.
Se que no es el hilo pero, podrias dar un consejo a los que vamos a recien salir para encontrar trabajo y sobretodo para no ser un simple picateclas?, soi consciente de la cantidad de candidatos con los que me voi a pelear y en internet hay exceso de información inutil que al final vuelven loco a uno.
Tengo claro que quiero dedicarme al backend pero todo lo que ve uno en videos o cursos es lo mismo y nadie te enseña realmente como llegar a una entrevista y que el recruiter se quede contigo en lugar de con los 3000 que hay delante o detrás.
Se que puede ser complicado establecer una guia o roadmap o lo que sea, pero mejor serán los consejos de alguien que parece estar metido y con gusto en el mundillo, casi como una sana obsesión.

3 respuestas
D

#26 Te estás respondiendo a tu pregunta. No consumas información inútil ni hagas cosas inútiles. Cuando encuentres información útil, presta atención. Transforma la información en resultados. Cuanto más crees, mejor.

La ingeniería es un arte creativo más. Crees que si pintas cada día el mismo retrato, sin cambiar nada, vas a progresar? Qué crees que va a pasar si estudias teoría del color, formas y volúmenes, iluminación, y luego experimentas con distintas técnicas? La maestría en una disciplina no se obtiene de hacer siempre lo mismo de la misma manera durante 20 años.

Eres un pintor y has pasado 20 años pintando a tu mujer, que posa para ti todas las mañanas. Un día decides ir a la plaza del pueblo a pintar a más gente para ganar un dinerillo extra. Un niño y su padre se acercan y te piden un retrato sonriente. Aceptas sin dudar. Al mirar al niño, notas que no tiene el pelo largo ni rubio como tu mujer, ni la misma forma de cara, ni la misma ropa.

Los únicos programadores que te van a decir que llevan 20 años haciendo lo mismo, de la misma manera, entre excusas de que se van actualizando y que han evolucionado y son muy buenos, son los programadores que no saben pintar.

Nadie puede decirte qué camino tomar porque solo tú sabes dónde estás, de dónde vienes y adónde quieres ir. Desconfía de cualquiera que te dé pasos a seguir. La verdad es más simple: si caminas en una buena dirección, llegarás a un buen lugar. No te preocupes tanto por el destino exacto.

1 1 respuesta
Jastro

#26 Quitando la parte de conocimiento tecnico, que eso es otro cantar, yo te dare un consejo sobre como afrontar entrevistas

La actitud dice mucho del un candidato, si estas nervioso, te cuesta decir palabras, te bloqueas, suele ser algo determinante, a no ser que seas un dios en programacion, lo importante es proyectar seguridad.

Si hay algo que no sabes hacer, no te cortes, dilo abiertamente. Nos gustaria que usaras "Framework random".

  • No he usado nunca Framework Random, pero si me dais el tiempo suficiente, no deberia costarme adaptarme y trabajar con el.

Puede parecer una gilipollez, pero si vas con esa proyeccion, es mucho mas facil que te cojan, porque das la sensacion que pase lo que pase vas a moverte.

2 1 respuesta
D

#27 Nlo había visto de esa manera, aunque tiene su logica más aún siendo algo que creas desde 0 con cualquier idea que se te ocurra, y soy una persona que no se conforma con lo que tiene delante pero no se como se puede tomar eso aqui, quizás alguien crea que quieres reinventar la rueda, a mi me mola verte que no paras de crear cosas todo el rato y me da envidia sana por que es lo que dices plasmas lo que se te ocurra y lo creas, me quedo con lo de ''no hacer siempre lo mismo de la misma manera durante 20 años'' y estoy deacuerdo en el resto.

#28 Por la actitud no me preocupa, al contrario, tengo mucha predisposición a aprender y preguntar cualquier cosa, no cierro ninguna puerta no solo por tener esa tan ansiada primera experiencia si no por que no quiero encasillarme y sencillamente hacer las 4 lineas de turno y cobrar a fin de mes, yo quiero ser lo mejor posible en mi trabajo, aprender, comprender y saber aplicarlo, sobretodo explicar el por qué, si hace falta aprendo cobol mismo, siempre y cuando la empresa me valore, pero tienes razón no es la primera que escucho que se tiene muy en cuenta la actitud en una entrevista, mucha gente suele recomendar lo mismo (proyectos, github, etc...), pero recien salido del cascarón a no ser que le pongas ganas e interés de verdad no creo que esperen grandes cosas ahí, por eso estoy en este hilo.

1 respuesta
laZAr0

#26 yo en IT no tengo experiencias como entrevistado, pero siempre he ido a las entrevistas mentalizado de que ya conozco al entrevistador, como si fuese un antiguo amigo o un familiar al que hace tiempo que no veo y tengo ganas de hablar con él y contarle lo que hago. Eso es importante sobre todo para dar una buena primera impresión, en el momento en el que te reciben o abres la puerta de un despacho. Tampoco te pases de informal, pero si vas pensando que es la persona de la que depende que te contraten o tu futuro jefe, que lo es, pueden venir los nervios y las inseguridades. Sé sincero y demuestra ganas de aprender.

1 respuesta