Prueba técnica - SSE

Wei-Yu

Buenas, traigo Otra Prueba Técnica tm para "senior software engineer". Después de preguntar por feedback sólo me han dicho

The solution is correct, but we just consider your profile based on the solution, on mid-level - and we definitely need someone more senior.

Así que a ver si alguien se anima y me saca los colores. Mi expectativa era tener una sesión un poco de "pair" durante la entrevista técnica en la que hablar cosas concretas. Normalmente invierto más tiempo en meter un exception middleware, buen logging y más cosas, pero al final son cosas puramente técnicas que no aportan mucho (al margen de qué loggear, cómo y dónde) así que decidí pasar y hacer algo simple.

La prueba (con el enunciado al final):

NSFW
kidandcat

El problema no es tuyo, es de estas empresas. Un día entenderán que precisamente es el SSE el que va a hacer las cosas simples y efectivas, mientras tanto seguirán dándose de palos.

Mejor que no hayas seguido el proceso, hay sitios mejores, no pierdas la esperanza.

PD: Y más aún con ese feedback de mierda

1
PiradoIV

Sin mirar el código, yo creo que es una práctica bastante habitual, para ofrecerte menos salario.

Soltrac

He visto tu código por encima y no dista mucho de cualquier implementación de clean code en c#.

No se, no me muevo en estos mundos, no se q tendría que hacer un SSE diferente a ti.

Por otra parte, como no se como son las pruebas técnicas, entiendo que no te piden ningún tipo de seguridad y ese control se hace en otro lado, porque tu implementación carece de cualquier tipo de seguridad.

1 1 respuesta
aren-pulid0

El código correcto, me parece feo que te hayan bencheado sin dar pie a una discusión.

Tal vez esperaban que hicieras la implementación manejando la concurrencia o algo event driven...

Sphere

Si no te dan feedback más concreto ni me rayaría, es la excusa que han querido soltar porque tendrán otros candidatos preferidos. Cualquier respuesta tipo "jaja salu2 pero queremos a alguien más senior" va directamente a la basura. Otra cosa es que te hubieran dado explicaciones concretas o, si hubiera sido una empresa decente, te hubieran invitado a una entrevista para discutir tu solución y darte una oportunidad para defender tus decisiones de diseño.

Lifecasi0

También podrías haberte montado scripts para lanzar las cosas, en lugar de tener que hacerlo a maneja, desde carpetas concretas.

1 respuesta
Wei-Yu

en un principio iba a pasar del proceso porque me dio mala espina desde el primer email pero como conocía a la empresa dije bueno, malo será

luego ya viendo el percal la dejé por aquí por si alguien quiere comentar algo o si alguien más junior tiene curiosidad y así al menos no lo siento como tiempo perdido

#4

Por otra parte, como no se como son las pruebas técnicas, entiendo que no te piden ningún tipo de seguridad y ese control se hace en otro lado, porque tu implementación carece de cualquier tipo de seguridad.

Es una kata, ese tipo de cosas no las programas en estos escenarios; mil cosas en ese plan que te llevarían horas y horas. En una prueba el scope no es meter usuarios, auth y otras tantas.

#7 y el script lo tendrías que ejecutar desde un dir que sería... el root del proyecto. Que de todas formas lo que dices es un script guarro de 3 líneas bash, tampoco me parece algo útil.

1 respuesta
isvidal

Hasta que punto te puede hacer ChatGPT una prueba asi?

1 respuesta
Wei-Yu

#9 escribir cuatro líneas de boilerplate no es un bottleneck; construir conocimiento sobre lo que vas a desarrollar es algo que no puedes hacer si "se lo tiras a chat gpt", y eso es algo que necesitas hacer para poder tener una conversación funcional durante la prueba técnica.

De hecho esto es literal un template que tengo que usé en el curro para la prueba técnica y que luego usé para montar nuestro microservicio principal xd. Tardé más en actualizar libs y cosas que tengo por ahí que en escribir lo que hay en el repo, e invertí más tiempo en pensar que en escribir.

Soltrac

#8 Ya ya supongo, era por buscarte un pero xDDDD. Yo desconozco el mundo este empresarial y estas mierdas.

Como ya te digo, no dista mucho del típico template de clean code. Desconozco como alguien "lo haría mejor" y como no se hasta donde hay q llegar, a mi personalmente me daría la espina que controlas asp net core sin problemas.

No se, hacer estas cosillas son así, no entiendo que es lo que busca la empresa realmente. Entiendo que es una excusa y punto.

1
Wei-Yu

puto criptohippie qué envidia me das

1
shaba

Hey, no tengo idea de .NET.. me lo he mirado por encima. Es normal en estas Katas el formato? Como es que no has puesto un docker-compose levantando una DB?

En cuanto a tu Schema y queries.
Tus movements y tus accounts son dos tablas en un DB de verdad?

Tu FindAccount hace 2 queries, si duplicaras el balance en Account y hicieras un update cuando haces withdraw y insert te quitaria este problema.
Todas tus operaciones utilizan FindAccountTopMovement, si tienes el balance duplicado en account, no tienes que hacer esta query(aunque digas que es cheap, no entiendo como el order by es cheap).

Tu ListMovements hace una query extra innecesaria, primero haces findAccount, innecesario?(la tabla de movements ya tiene la account id).

En cuanto a las races deberías gestionarlas en el código. IMO no puedes argumentar un caso como "otherwise abort." en un contexto de banking donde potencialmente se pierde dinero.

p.s: yo creo que la gracia del ejercicio son las races etc, lo otro es muy standard

1 1 respuesta
Wei-Yu

#13 gracias por ojear <3

Si le metes un data store entre conectar y enchufar cosas ya echas más del tiempo que ya eché en toda la prueba sólo para poder decir "metí dos tablas y ahora hago un select real sobre un rdbms".

Con el balance fuera de la cuenta sí que no me quedé muy contento pero no lo metí dentro no tener el problema de mantenerlo sincronizado. Pensándolo dos veces es algo que se lleva la transaccionalidad (que tampoco sale gratis pero eso ya es una micro optimización). No hay order by (que no es barato para nada como señalas), es un top a pelo sobre el identity, que eso sí que es un mojón del quince la verdad. Creo que hay algún engine que sí garantiza (me suena pg? pero creo que ms sql no por ejemplo) el ordering, pero aún así ea información no es algo que deberías tirar a un pozo como ese.

Las queries múltiples por request acaban saliendo sí o sí en prácticamente todos los flujos, aunque sea para reglas simples sobre aggregates de dominio y si es tirando de la PK y tu recurso es pequeño, sin un benchmark de por medio o unas expectativas de volumen de tráfico concreto prefiero tener la semántica porque entre cachés y otras gaitas el footprint debería ser ínfimo.

El texto sobre la race condition sólo son formas de abordarlo, de tener que implementarlo iría por la cola si tuviese sentido (que no lo sé porque no curro en payments y no es lo mismo asincronía de medio segundo que de media hora aún siendo ambas asíncronas). Aún así sigues teniendo la posibilidad de tener dirty reads con el error (otherwise abort), porque es eso o petarte la concurrencia. Cómo resolverías eso application side? Un mutex?

1 respuesta
Zireael

Hello. Soy junior pero trabajo a diario con .net. Este finde le echo un ojo a ver si aprendo algo nuevo, gracias por compartir.

JuAn4k4

Pues yo veo varias cosas, metes muchas separaciones de proyectos y clases para al final meter toda la lógica en la implementación del repositorio.

No gestionas el race condition que mencionas ni la transaccionalidad de leer un balance y usarlo después para cambiar el siguiente balance (que es obvio es el objetivo de la prueba).

El dominio/problema de las cuentas es un caso perfecto para DDD/EventSourcing, además de ser el típico ejemplo usado. Por ejemplo usando Akka Actors no hubiera costado mucho hacer la prueba.

Además deberías gestionar problemas específicos del dominio como el currency/moneda para dar sensación de seniority.

Al final un mid-level hace lo básico y ya, que es lo que hiciste.

2 3 respuestas
aren-pulid0

No conocía el modelo de actores, el op justo hacía referencia por arriba a como gestionar la concurrencia

De la wikipedia

The actor model in computer science is a mathematical model of concurrent computation that treats an actor as the basic building block of concurrent computation. In response to a message it receives, an actor can: make local decisions, create more actors, send more messages, and determine how to respond to the next message received. Actors may modify their own private state, but can only affect each other indirectly through messaging (removing the need for lock-based synchronization).

shaba

#14 Igual Juanito te puede ayudar más , no tengo ni idea de todo el ecosistema de java ni de actors. Yo soy más de comDB2 por razones obvias. Mutex local no puedes porque diferentes requests pueden ir a multiples instancias de tu servicio(supongo que no te referías a eso).
Supongo que la solución kafka es la obvia, donde todas las mismas ids van al mismo consumer para garantizar orden y luego incrementas el balance. (aunqe aun hay una race)
Si no utilizas queue tienes que hacer una db transaccion para incrementar el balance.

La otra forma es hacerlo "lazy", nunca calcular los balances en insert y 1) los calculas on demand y los insertas cuanto te los piden. 2) tienes un job que los calcula cada X tiempo los que no estaban aun calculados

1 respuesta
kidandcat

#16 Es que al final las pruebas técnicas son un filtro más en el proceso de recruiting. Si quieres que trabaje a ese nivel, págalo. Y las empresas que no entiendan eso son las que luego dirán que no encuentran gente cualificada...

Kaledros
#16JuAn4k4:

metes muchas separaciones de proyectos y clases

No tengo ni idea de como se hace un proyecto en C#, pero esta es la sensación que me ha dado también, que había un montón de clases para algo que a priori debería ser mucho más sencillo.

De todas formas, no sé en qué iban a ver la seniority en la prueba que te han puesto. Si lo que querían era ver hasta qué punto puedes añadir complejidad y escalabilidad, metiendo Kafka, event-driven y tal, me parece un poco así porque el enunciado no dice nada de eso.

1 1 respuesta
desu

Leyendo solo el README te han tirado por conocimientos del dominio. Tanto tecnicos com no tecnicos.

Has usado una DB relacional en lugar de algo orientado a logs, lo has hecho in-memory y las race-conditions / consitencia y eventualidad que es lo unico que importaba no lo has hecho.

El codigo ni lo he mirado.

La proxima prueba al menos dedicale 15 minutos a googlear como se solucionan problemas en banca.

Wei-Yu

#16 la lógica está en la capa de dominio. Hay lógica en el repo, pero derivada de que no estoy tirando de una DB y que no lo pensé mucho. Es buen punto donde introspeccionar para futuro, no quería invertir tiempo y al final me pegué un tiro en el pie. No sé si tienes/quieres añadir algo más por ahí, pero encantado de leer. Con el ejemplo de tratar problemas específicos del dominio te refieres a usar valueobjects para representarlo?

Tanto tú como #20 habéis mencionado excesiva separación de clases/módulos, tenéis algún comentario adicional al respecto?

#18 el mutex lo comentaba porque no sé por dónde quieres tirar con gestionlarlo app-side, pero releyendo creo que te entendí mal en tu primer comentario. Tengo cero exp con comdb2, cuando dices que que eres más de ello por razones obvias es por exp tuya o tradeoffs obvios que existen?


Tendría que haber profundizado más en la race condition y haberme explayado un poco mejor en el readme (revisando ahora el código de la parte de infra ni siquiera llegué a meter un comentario al final la transaccionalidad, a pesar de tenerlo en mente al redactar el readme). Al modelar a pesar de haber buscado formas de hacerlo (ej: recuerdo leer sobre lo que se comenta de calcular el balance on demand) acabé dejando una ñapa.

Muchas gracias por dedicarle un tiempo a escribir en el hilo.

JuAn4k4

Con Akka lo haces en dos patadas porque te dan persistencia, consistent hashing, event sourcing, actor model, sincronización del estado y tal de gratis. Puedes decir que para la prueba has usado eso al dártelo hecho ya que encaja bien con el problema. En el fondo la parte senior es encajar el problema con la solución técnica.

Que luego todo depende de los recursos, necesidades, etc que tengas en ese momento. Para una prueba así lo mejor es hablar del problema y posibles soluciones que hacerlo en sí. Al hacerlo yo diría que es un PoC en el que como digo simplificas para no perder mucho el tiempo y dices: Uso Akka que me da todo hecho, pero podría haber mejores soluciones al problema. Y hablas de escalabilidad, (sharding, particiones), resilience, performance, migraciones, yada yada.

Lo de hacer muchas clases, y proyectos, que has hecho un CRUD, en 1 clase eso se puede meter.

2

Usuarios habituales

  • JuAn4k4
  • Wei-Yu
  • desu
  • kidandcat
  • shaba
  • aren-pulid0
  • Soltrac